Skip to content

Make one store own worker lifecycle and wait results - #746

Merged
TheGreatAxios merged 7 commits into
mainfrom
cl-7269-make-one-store-own-worker-lifecycle-and-wait-results
Sep 1, 2026
Merged

Make one store own worker lifecycle and wait results#746
TheGreatAxios merged 7 commits into
mainfrom
cl-7269-make-one-store-own-worker-lifecycle-and-wait-results

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • One stored WorkerLifecycle owns worker state, report/error, retention, and physical handles. fail() is failed, not shutdown; closeOne after fail returns immediately.
  • wait_agents JSON is a projection of that lifecycle plus a per-install FleetMailbox (membership, pin, collected, interrupt override), not a second terminal store.
  • Operator cancel and close/send_input interrupt report wait status interrupted rather than failed. Headless exec finally cancels live sub-agents the same way TUI runtime-shutdown does.

Verification

  • bun run typecheck, bun run build, and bun run test pass
  • bun run check in this worktree: lint, typecheck, build, and 5744 tests pass

Fixes CL-7269

@linear-code

linear-code Bot commented Aug 31, 2026

Copy link
Copy Markdown

CL-7269

@TheGreatAxios TheGreatAxios left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 TheGreatAxios left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 TheGreatAxios left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 TheGreatAxios left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:203take() 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} without report-0; maxCompleted: 0 drops every first report. Could this return the pre-unpin snapshot, or otherwise retain the payload through delivery?
  • src/subagent/agent-fleet.ts:127 — each FleetMailbox permanently subscribes to the shared session store and discards the unsubscribe handle. Nested orchestrator runs create these mailboxes at src/subagent/run.ts:602 over the shared store passed at src/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 check exits 0 across lint, typecheck, build, and tests.

@TheGreatAxios
TheGreatAxios force-pushed the cl-7269-make-one-store-own-worker-lifecycle-and-wait-results branch 2 times, most recently from df55400 to d2da283 Compare September 1, 2026 04:20
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.
@TheGreatAxios
TheGreatAxios force-pushed the cl-7269-make-one-store-own-worker-lifecycle-and-wait-results branch from d2da283 to b924351 Compare September 1, 2026 04:33
@TheGreatAxios
TheGreatAxios merged commit 2fd15a8 into main Sep 1, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant