A terminal that stopped draining the pty parked the writer thread inside
its tty write while it held the stderr lock; the next inline stderr write
from the event loop (mouse toggle, notification, kitty clear) deadlocked
the loop, and /quit hung on the unbounded writer join and the teardown
writes.
EscapeWriter queues out-of-band escapes on the frame writer: the mouse
capture toggle, notifications (title, progress, protocol), the auth
cursor, gboom keyboard flags, the wrap clipboard request, and the kitty
clears (queued per agent view and merged into the frame's post-flush,
nested subagent views included). The $EDITOR/$PAGER handoff aborts when
the writer does not drain. WriterThread::join_within and the teardown
run under a 2 s grace; after a stall fd 2 is silenced, the exit hints,
relaunch and update prints are skipped, and the panic hook keeps only its
log report.
Ported from upstream 1.0.19 (grok-build EscapeWriter, WriterJoin,
run_bounded_teardown), extended to the remaining inline writes.
Claude-Session: https://claude.ai/code/session_01RUqV8HVGXcAETyYbZ2tPQ4
The full-workspace gates had never run on this platform: collapsible
ifs in the Windows shell probe, a same-type cast in the crash handler,
an unused AsRawHandle import, and the sandbox smoke-test example
building its unix-only body (libc, kernel enforcement) unconditionally.
The example now stubs main off-unix; formatting reflow from cargo fmt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KSy9S31pZNWXtRZNVJ1sDf
Port of upstream grok-build 0.2.113/0.2.114 fixes, extended to Kigi's
startup order.
- kigi-tty-utils runtime module: worker-cap policy (8 max) — tokio's
per-core default pins 100+ thread slots on many-core shared hosts
against RLIMIT_NPROC / pids.max, and later spawns die with EAGAIN.
- kigi-bin builds the main runtime with capped workers and reports an
out-of-threads host with a diagnostic + exit(1) instead of a panic.
- The pre-runtime optimization threads (HTTP warmup, early model
prefetch) spawn recoverably and degrade — their panic would have
preempted the runtime's own diagnostic.
- The per-session actor thread and its runtime report spawn/build
failure through the existing acp::Error / AgentBuildError boundaries
(new RuntimeBuild variant) instead of panicking the agent host.
- fsnotify's watcher thread spawn maps into FsNotifyError::WatcherStart
so callers degrade instead of crashing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KSy9S31pZNWXtRZNVJ1sDf
Port of upstream grok-build 1.0.1 (landed upstream 2026-08-06).
A child wedged in an uninterruptible kernel syscall (D-state) never
observes SIGKILL, and a background descendant can hold the output pipes
open past the kill; both previously stalled tool futures without bound.
- kigi-tty-utils: KILL_REAP_TIMEOUT (5s) + reap_killed_bounded — wait
for an already-killed child at most the bound, then abandon the corpse
to tokio's orphan reaper.
- local_terminal: pipe readers share their buffer with the spawner and
join under the reap bound on both exit arms (aborted readers are
awaited so no tail bytes race the take); the whole tree is enrolled in
a ProcessGroup and group-killed on timeout; the timeout arm returns
the synthetic result instead of waiting on the corpse. Grandchild
kill + prompt-return pinned by a ported unix regression test.
- kigi-tools: reap_killed_search_child wrapper; grep's four kill sites
reap bounded; glob's stderr goes to null (an unread pipe blocks rg on
warning backpressure) and its truncation kill reaps bounded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KSy9S31pZNWXtRZNVJ1sDf
Sweep every first-party crate source (1956 .rs files) to the project comment
guidelines: delete redundant restatements, decorative banners, change
narration, and end-of-line comments; keep and tighten the crucial ones
(invariants, bug rationale, SAFETY blocks, ported-source attribution).
No functional code changed. Every edit is proven comment-only against the
prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a
separate doctest-fence check. Where removing a comment made rustfmt or clippy
want to re-lay-out adjacent code, the minimal triggering comment is restored so
code tokens stay byte-identical.
Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy
--workspace --all-targets (0 warnings).
Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for
these guidelines (flags banners, end-of-line comments, change narration, and
commented-out code).