fix(runtime): let the pi process verdict win over a failed write - #224
Merged
Merged
Conversation
eddiearc
reviewed
Sep 13, 2026
Owner
Maintainer follow-up(Fable vs GPT-6 Astra)方向同意:stdin 写失败不该盖住真实的 spawn verdict。 Fable 倾向 rebase 后合;GPT-6 Astra 消融后建议先缩小实现再合(我们跟这个):
相关:#223。 |
itswl
force-pushed
the
fix/pi-rpc-write-failure-masking
branch
from
September 14, 2026 01:53
124561f to
10d1657
Compare
Contributor
Author
|
按四条改完了(head
验证: |
Owner
|
复看 head
CI 全绿。maintainer 侧倾向 APPROVE;合入仍等 idan 明确 yes。 |
A spawn failure was reported as whichever error landed first: the
request's stdin check ("stdin is unavailable") or the process verdict
("spawn ... ENOENT"), and fail() keeps the first error — so the write
path could mask the real cause. Defer the write error by a single turn
(next tick runs before the check phase, so a real spawn/exit verdict
always wins) and report it only when no verdict arrives: no arbitration
timer, no pid/exit heuristics on doubles, and concurrent write failures
collapse into the client's single first-error terminal state.
Tests cover a real missing executable and missing working directory, a
live process with broken stdin, concurrent write failures, and a short
request deadline.
Bumps the package patch version (0.5.9 -> 0.5.10) per the Owner policy.
Co-Authored-By: Claude Code <noreply@anthropic.com>
itswl
force-pushed
the
fix/pi-rpc-write-failure-masking
branch
from
September 14, 2026 14:15
10d1657 to
a325714
Compare
Contributor
Author
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
When a pi spawn fails (missing working directory, ENOENT on the binary), the client reported whichever error landed first — the request's write check (
stdin is unavailable) or the process verdict (spawn … ENOENT) — andfail()keeps the first error. The write path often won, so the real cause was lost: users sawPi RPC get_available_models write failed: stdin is unavailable, or the classifier'spi is not installed; neither points at the spawn failure. Filed as #223.Change
src/runtime/pi-rpc-client.ts: a failed write now defers to the process verdict when the child is already gone (pid === undefined, or an exit code/signal is recorded). The write error is held as a bounded (500 ms) fallback so theerror/exithandler — which carries the real reason — can fail the client first. A live process with a broken stdin still fails immediately with the write error, and the wait is always bounded so a request can never hang on a verdict that never arrives.PiRpcProcessgains optionalpid/exitCode/signalCode(additive; existing doubles and theProcessLikecast inruntime-adaptersstay assignable).test/unit/runtime/pi-rpc-client.test.mjs: a dead-spawn double (destroyed stdin, no pid) proves the process verdict wins andstdin is unavailablenever masks it; a second case proves the fallback stays bounded (< 2 s) when no verdict ever arrives.Validation
Before, the same setup surfaced
stdin is unavailable(or, timing-dependent, the classifier'spi is not installed).bun test test/unit/runtime/pi-rpc-client.test.mjs→ 11 pass / 0 failbun test test/unit/runtime/→ 233 pass / 0 failbun run build✅ ·bun run typecheck✅ ·bun run licenses:check✅ ·bun run publication:check:tree✅bun run test:unit→ 897 pass / 1 skip / 1 fail. The single failure is the pre-existing environmentalthree-Agent live acceptance is opt-in, hermetic by default, and fixture-verifiable, which also fails on unmodifiedmainhere.How this composes with the rest of the cluster
This fixes the masking at the client layer, so every consumer of the raw error (logs, status, session-start failures) now sees the spawn reason. The final user-facing classification is #215's job — it keeps the raw reason when the executable was already resolved and exists, which turns the message into "verify the launch environment" instead of "not installed". #212/#214 remove the setup-path trigger entirely, and #218/#219 remove the ~4 s the catalog still spends waiting on
close()(the client request itself now rejects in 7 ms).Fixes #223
🤖 Generated with Claude Code