Make one store own worker lifecycle and wait results - #746
Conversation
TheGreatAxios
left a comment
There was a problem hiding this comment.
skywalker · approve
One stored WorkerLifecycle owns worker state; wait_agents projects from it plus a per-install FleetMailbox; headless exec finally cancels live workers.
No blocking findings.
TheGreatAxios
left a comment
There was a problem hiding this comment.
critic · comment
Wait JSON is a projection of stored lifecycle plus mailbox overlay; leftover resolve/reject methods are gone.
- docs/ARCHITECTURE.md:222 — operator cancel docs omit the in-flight window: cancelled+inFlight still projects running until settleRun
- src/exec/runner.ts:133 — cancelAll is not try/caught; a throwing subscriber would skip close/dispose
TheGreatAxios
left a comment
There was a problem hiding this comment.
greybeard · comment
Session store owns lifecycle; FleetMailbox is overlay membership, pin, collected, and interrupt — not a second terminal store. fail() is failed, not shutdown.
No architectural blockers.
TheGreatAxios
left a comment
There was a problem hiding this comment.
Review · Request changes
Worker wait results now project one stored lifecycle through a per-install mailbox, and headless exec shutdown cancels live workers.
Findings
src/subagent/agent-fleet.ts:203—take()unpins before returning a fresh snapshot, so synchronous retention pruning can delete the session and drop the report from its first delivery. With the default cap, completing 21 non-retained workers and collecting them in reverse order returns the oldest result as{"status":"done","collected":true}withoutreport-0;maxCompleted: 0drops every first report. Could this return the pre-unpin snapshot, or otherwise retain the payload through delivery?src/subagent/agent-fleet.ts:127— eachFleetMailboxpermanently subscribes to the shared session store and discards the unsubscribe handle. Nested orchestrator runs create these mailboxes atsrc/subagent/run.ts:602over the shared store passed atsrc/subagent/agent-fleet.ts:651, so completed orchestrators remain retained and every later session notification invokes all stale mailboxes. Could mailbox/toolset disposal unsubscribe this listener?306c252e— the commit body contains a 203-character line, exceeding the repository's 72-character body-line limit.
Notes
bun run checkexits 0 across lint, typecheck, build, and tests.
df55400 to
d2da283
Compare
Snapshot status and verb lifecycle are now projections of one stored union. fail() is a first-class failed state, not shutdown, so wait and resume can tell a throw from a close. Pin/unpin keep uncollected wait results off the display-cap prune.
Wait JSON is a projection of stored worker lifecycle plus a per-install overlay for membership, pin, collect-freeze, and the close/send_input interrupt edges that must unblock before the session record is terminal. Spawn and resume settlement write only the session store.
Wait JSON is a projection of stored WorkerLifecycle plus a per-install mailbox. Drop leftover resolve/reject methods that no longer write a second terminal store. Keep the dependency field name fleetRecords so call-site churn stays a rename of the type and factory.
Headless exec finally cancels live sub-agents the same way TUI runtime shutdown does, then closes the primary agent and disposes the toolset. cancelAll is fire-and-forget and does not serialize closeOne.
fail() of a live persisted agent must invoke the registered close so close_agent can recover after a resume followup throw. Mailbox register re-pins on call-id reuse, and a pruned mailbox member is a tombstone instead of eternal running. Wait/task cancel stays interrupted.
A completed worker pruned from the session store was wait-reported as interrupted because snapshot hard-froze missing sessions. Capture the live wait projection and retention tombstone so wait keeps done/failed, and only unknown missing sessions stay interrupted.
d2da283 to
b924351
Compare
Summary
WorkerLifecycleowns worker state, report/error, retention, and physical handles.fail()isfailed, notshutdown;closeOneafter fail returns immediately.wait_agentsJSON is a projection of that lifecycle plus a per-installFleetMailbox(membership, pin, collected, interrupt override), not a second terminal store.send_inputinterrupt report wait statusinterruptedrather thanfailed. Headless execfinallycancels live sub-agents the same way TUI runtime-shutdown does.Verification
bun run typecheck,bun run build, andbun run testpassbun run checkin this worktree: lint, typecheck, build, and 5744 tests passFixes CL-7269