Skip to content

Commit 1726590

Browse files
fix(server): settle child threads on provider death (ADA-149) (#205)
* fix(server): settle child threads on provider death * fix(server): harden provider-death settlement * fix(server): guard unarchived session projections * docs: plan ADA-149 round 3 P2 fixes * fix: guard stopped child settlement during replacement start * plan ada149 session projection marker * fix unarchived stopped projection marker * fix session-derived terminal reconciliation --------- Co-authored-by: wizzoapp[bot] <254688279+wizzoapp[bot]@users.noreply.github.com>
1 parent c1f0260 commit 1726590

4 files changed

Lines changed: 1007 additions & 156 deletions

File tree

ADA-149-round3-p2.plan.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# ADA-149 Round 3 P2 Plan
2+
3+
Intent: fix the two confirmed PR #205 P2 regressions in `ChildThreadCoordinator` without changing provider-death semantics outside terminal child settlement. Stopped session-set events must not destroy a pending replacement start, and projection-restored terminal children must surface provider death `lastError` text instead of generic turn/session wording.
4+
5+
Blast radius: `apps/server/src/orchestration/Layers/ChildThreadCoordinator.ts` live session-set handling, replay session-set handling, projected lifecycle reconciliation, one-shot projection settlement, archive projection settlement, wait/wake result text, dispatch-lease release, `subagent_wait_deliveries`/promoted fallback behavior, restart replay from persisted orchestration events, and `apps/server/src/orchestration/Layers/ChildThreadCoordinator.test.ts`.
6+
7+
Edge-case matrix and red-first tests:
8+
9+
- Ordering both ways: stale stopped before replacement session-set must remain pending; stale stopped after replacement running is already covered. Red test: `does not settle stale stopped while replacement start is pending`.
10+
- Duplicates/replays: persisted stale stopped with replay pending maps must not settle if a replacement start is replayed later/earlier; add replay only if cheap, otherwise document live coverage and handler symmetry.
11+
- Crash-between-steps: projection-restored stopped/error after terminal projection must preserve `session.lastError` through wait/wake. Red test: `surfaces provider-death lastError from non-running projected lifecycle`.
12+
- Same-timestamp ties: keep existing timestamp ownership tests unchanged; the new pending-start guard is independent of timestamp ordering.
13+
- Version skew/concurrency: keep `error` session-set behavior unchanged and only skip ambiguous `stopped` settlement while pending starts exist.
14+
15+
Smallest-change argument: add a stopped-only pending replacement-start guard at the two event-handler settlement points and upgrade terminal error text through local `lastError` preference helpers. A same-turn pending marker identifies replacement-start races while preserving existing initial placeholder recovery. Do not add new settlement machinery; later replacement running/failure and existing wait reconciliation remain responsible for eventual settlement.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# ADA-149 session projection marker plan
2+
3+
Intent: Fix the accepted PR #205 review defect where a stopped/error provider session already reflected in the projection can be converted through an interrupted/error latest turn without `fromSessionProjection`. The fix keeps stale post-unarchive projection-only provider-death failures pending on boot instead of waking the parent from pre-unarchive state.
4+
5+
Blast radius: `apps/server/src/orchestration/Layers/ChildThreadCoordinator.ts` projection lifecycle reconciliation, boot replay projection guards, one-shot register/wait reconciliation, live session/turn handlers, pending wake pruning, dispatch lease seeding, and `apps/server/src/orchestration/Layers/ChildThreadCoordinator.test.ts` restart/unarchive tests. Consumers that could break are parent wake injection persistence, foreground waits, detached child settlement, provider-death lease release, archived/unarchived child replay, and projection snapshot readers after restart.
6+
7+
Edge-case matrix:
8+
9+
- Ordering archived -> unarchived -> no new turn with stopped session + interrupted latest turn: red-first test `keeps inactive unarchived stopped interrupted projections pending on boot`.
10+
- Ordering archived -> unarchived -> no new turn with error session + error latest turn: red-first coverage in the same test table.
11+
- Live turn-derived interrupted/error settlement after registration: existing tests `settles error turn-diff as failed`, `settles session-set ready with a completed projected turn as completed`, and provider-death live tests must remain unmarked behaviorally.
12+
- Duplicate/replayed boot events: existing replay reconciliation tests around unarchive terminal pruning and provider-death replay must remain idempotent.
13+
- Crash between wake persistence and restart: existing pending dispatch restart/pruning tests must remain unchanged because marker only affects projection-only skipped settlement.
14+
- Same-timestamp ties: no timestamp ordering changes; existing post-unarchive wake retention tests remain the guard.
15+
- Version skew with older logs lacking terminal turn events: marker applies only to current projection-derived session failures, preserving old live/replay event outcomes.
16+
- Concurrency/replacement start: existing pending replacement-start tests must still prevent stale stopped sessions from settling.
17+
18+
Smallest-change argument: leave `turnTerminalOutcome` live-turn semantics unchanged and add a narrow projected terminal-session wrapper/guard for projection lifecycle and one-shot wait/register reconciliation. This avoids marking live turn-diff/session-set results while giving boot unarchive guards the structural signal they already expect.

0 commit comments

Comments
 (0)