fix: isolate standalone bridge process generations
Summary
Follow-up to #233 and the two post-review P1 findings:
- ignore stdout/stderr callbacks from retired child generations so a stale
endcannot flush replacement output - fence configure completion to the child that received configure, preventing an old continuation from marking a replacement configured
- retire the child and clear pending state for both synchronous and asynchronous stdin write failures
- classify in-flight standalone failures as outcome-unknown so bash host fallback cannot blind-replay a possible mutation
Request outcome contract
- a child already known to be unwritable before a request is queued can still be replaced before dispatch
- after write initiation or an in-flight child teardown, the outcome is
UNKNOWN; callers receive verification guidance and host fallback is ineligible - no request is replayed across process generations
Review findings addressed
- https://github.com/cortexkit/aft/pull/233#discussion_r3037020509
- https://github.com/cortexkit/aft/pull/233#discussion_r3037020510
Verification
bun test packages/aft-bridge/src/__tests__— 488 passed, 14 skippedbun run --filter @cortexkit/aft-bridge typecheck- Biome check on all five changed files
- public barrel driver: unknown-outcome error exported, fallback ineligible, UNKNOWN/no-blind-retry guidance present
All commits are SSH-signed and based on merge commit 7ea58ee2.
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
Summary by cubic
Isolates bridge process generations to prevent stale-child output, cross-generation configure completion, and blind replay after stdin write failures. Previously, retired children could flush replacement stdout, configure completion could carry over, and in‑flight standalone failures were treated as retryable; now we fence I/O and configure to the owning child, retire on write errors, and surface an unknown‑outcome error that blocks bash fallback.
- Introduces
BridgeTransportUnknownOutcomeErrorandBRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION; exported fromaft-bridge. - Treats stdin write failures (sync and async), crashes, and signals as unknown outcome: clears pending, rejects with unknown‑outcome error, and invalidates the current child; no request is replayed across generations.
- Ignores stdout/stderr
data/endfrom retired children; only the current child can mutate buffers. - Fences configure: ties warnings, version check, and completion to the child that started configure; if the child changes, throws
BridgeTransportUnavailableErrorinstructing a retry on the replacement. - Updates error adaptation to append unknown‑outcome guidance and to exclude unknown‑outcome errors from
isBashTransportDeadError, making bash host fallback ineligible.
Migration
- If you special‑case transport failures, handle
BridgeTransportUnknownOutcomeErrorexplicitly: verify actual state before retrying and never blind‑retry mutations; do not route these errors to bash fallback. No other changes required.
Greptile Summary
This PR isolates standalone bridge process generations and introduces an explicit unknown-outcome error contract to prevent unsafe mutation replay.
- Fences configure completion and stream callbacks to their originating child.
- Retires children after synchronous or asynchronous stdin write failures.
- Prevents bash host fallback for standalone requests that may already have executed.
- Exports and tests the new unknown-outcome error contract.
Confidence Score: 4/5
The timeout-escalation gap should be fixed before merging because an in-flight mutation can be rejected without the required outcome-unknown guidance.
Generation fencing and write/crash handling are improved, but handleTimeout still emits an untyped sibling-abort error after requests may have reached the child, bypassing the new no-blind-retry contract.
Files Needing Attention: packages/aft-bridge/src/bridge.ts, packages/aft-bridge/src/error-contract.ts
Important Files Changed
| Filename | Overview |
|---|---|
| packages/aft-bridge/src/bridge.ts | Adds process-generation guards and unknown-outcome handling, but timeout escalation still rejects in-flight siblings with a plain Error. |
| packages/aft-bridge/src/error-contract.ts | Adds unknown-outcome guidance and disables bash fallback for the new error type, but cannot recognize the plain sibling-timeout rejection. |
| packages/aft-bridge/src/index.ts | Correctly exports the new error class and disposition constant. |
| packages/aft-bridge/src/tests/bridge-transport.test.ts | Adds focused generation and write-failure regressions but does not assert unknown-outcome classification for timeout-aborted siblings. |
| packages/aft-bridge/src/tests/error-contract.test.ts | Verifies fallback ineligibility and safety guidance for explicitly typed unknown-outcome errors. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Standalone request written] --> B{Response received?}
B -->|Yes| C[Resolve request]
B -->|Write or child failure| D[Retire child generation]
D --> E[Reject pending as outcome UNKNOWN]
E --> F[Verify state; never blind-retry]
B -->|Sibling timeout escalates| G[Reject siblings with plain Error]
G --> H[SIGKILL child]
H --> I[Unknown-outcome guidance is omitted]
Reviews (1): Last reviewed commit: "fix: block fallback for unknown bridge o..." | Re-trigger Greptile
Greptile also left 1 inline comment on this PR.
Context used:
- Knowledge Base — TypeScript AFT bridge: native and daemon-backed transport