feat(supervise): first-class continuity on graph edges — fresh | resume | steer, all ledgered - #725
Conversation
…sals — fresh | resume | steer as ledgered data
A delegates edge accepts continuity: 'fresh' | 'resume' (edge default;
spawn_agent takes a per-call override). A resume traversal targets a node
whose prior worker has SETTLED: the kernel spawns a NEW live worker bound
to the same node whose spawn context carries resume: { ofWorker, sequence }
(WorkerResumeContext) — the executor seam owns the session re-attachment;
the kernel keeps identity, ordering, ledger truth, and spend continuity in
the one conserved pool. Traversal caps count resumes exactly like fresh
spawns.
Fail-loud refusals at the tool: resume-no-prior (explicit resume with no
settled prior; the DECLARED edge default instead degrades to fresh on the
node's first spawn), resume-while-live (steer is the live-worker channel,
the error says so), resume-with-key (keys are run-once, resume runs again).
Resume lineage is process-local — the same boundary as the analyst-run
marker — and stated where it lives.
EdgeTraversal and the journal 'edge' event gain
continuity: 'fresh' | 'resume' | 'steer' — spawns stamp their effective
mode, every mid-run delivery into a live recipient (driver steer legs,
every analyzes delivery) stamps 'steer'. validateGraph refuses nonsense
values and analyzes edges carrying the field.
Threaded as continuityByProfile through SuperviseOptions →
SupervisorAgentDeps → DriverAgentOptions / serveCoordinationMcp →
CoordinationToolsOptions; runGraph derives it from delegates edges. Kernel
exports ContinuityMode, WorkerResumeContext, TraversalContinuity.
New example examples/graphs/shot-loop-resumed.ts (the VB shot shape as
data: shot 1 fresh, shots 2-3 resume the prior settled session), proven
offline in tests/examples/graph-topologies.test.ts; kernel continuity
suite in tests/kernel/graph.test.ts. Edges without continuity behave
byte-identically to before. Bump 0.127.0.
… pin resume-after-failed-prior policy A backend seam with no session re-attachment accepting a resume spawn would ledger continuity:'resume' over a brand-new session — a stamp asserting something that never happened. Refuse loud; session-resuming makeWorkerAgent seams are the resume consumers. Failed-prior resume is deliberately allowed (the seam decides salvageability) — now tested and stated.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — d2986340
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
tangletools · auto-approval · reason: drewstone_author · 2026-08-03T19:43:21Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Concerns | 2 (1 low, 1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 140.3s (2 bridge agents) |
| Total | 140.3s |
💰 Value — sound
Adds node-level session continuity (fresh|resume|steer) as plain data on graph edges — a clean new axis that the three existing primitives (process-resume, key, steer) genuinely don't cover, built on the existing makeWorkerAgent seam and edge ledger.
- What it does: A delegates edge (or per-call spawn_agent arg) may declare continuity: 'resume'. On any spawn after the node's first, the kernel resolves the node's most recent SETTLED worker (by profile.name = node id), mints a NEW live worker, and hands its executor seam WorkerSpawnContext.resume = { ofWorker, sequence } — the lineage the seam uses to re-attach the backend session. The kernel keeps identity, or
- Goals it achieves: Make 'fresh respawn vs session resume vs live steer' expressible as ONE FIELD on a graph edge, so a resumed shot-loop (shot 1 settles failed → shot 2 continues shot 1's session context, spend continuous in one pool) is data, not a hand-rolled driver loop. Secondary: eliminate ledger ambiguity — every hop now states how it continued, so 'did traversal 2 continue traversal 1's session or start fresh
- Assessment: Sound and in-grain. The change fills a real gap: I checked the three adjacent primitives and none covers 'spawn a NEW worker that continues a SETTLED prior worker's session'. Scope.resume/ResumedWork (types.ts:711) is PROCESS-crash recovery — it re-adopts settled work without spawning; key/SpawnOpts.key (types.ts:503) is idempotency — a completed key returns its cached result WITHOUT re-running; s
- Better / existing approach: none — this is the right approach. Searched for an existing mechanism to extend: Scope.resume (types.ts:711) is process-level crash recovery, a different concept; SpawnOpts.key (types.ts:503) is run-once idempotency, structurally incompatible (extending key to mean 'run again with lineage' would break its exactly-once guarantee); steer (types.ts:644 Scope.send) targets LIVE workers, not settled on
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error
🎯 Usefulness — sound
A coherent, fully-threaded continuity axis (fresh/resume/steer) that extends the edge-ledger and fail-closed spawn patterns in the codebase's grain, with comprehensive refusals and correct back-compat — no equivalent reinvented, no materially better approach.
- Integration: Fully reachable. continuityByProfile is plumbed through runGraph → supervise → supervisorAgent (both arms) → driverAgent → serveCoordinationMcp → createCoordinationTools (verified at graph.ts:718-721,933; supervise.ts:1587,1668; supervisor-agent.ts:509,592; coordination-driver.ts:367; coordination-mcp.ts:156). The per-call
continuityarg is a live MCP tool parameter (coordination.ts:1796-1810), - Fit with existing patterns: Excellent. Extends the established edge-ledger observability contract (continuity is a new column on EdgeTraversal/graph.ts:142-167 and the journal edge event/types.ts:939-944) and the established fail-closed spawn-resolution discipline (resolves before assignment/budget, coordination.ts:1862-1872). Does NOT compete with the
keyidempotency mechanism (explicitly refused resume-with-key) or steer - Real-world viability: Holds up. Refusals cover every realistic misuse and are tested (graph.test.ts: resume-no-prior, resume-while-live, resume-with-key, resume-after-failed-prior, nonsense value on edge, continuity-on-analyzes-edge). Racing resumes are safe: resolveContinuity is synchronous, reads the live view + ledger, and hands off to scope.spawn with no await gap (coordination.ts:1114-1167, 1884-1888). latestSettl
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🔎 Heuristic Signals
🟡 Cruft: console debug added examples/graphs/shared.ts
- console.log(
🎯 Usefulness Audit
🟡 'resume' is overloaded between continuity-resume and durable Scope.resume [ergonomics] ``
The word 'resume' now names two distinct concepts at two layers: continuity 'resume' (WorkerResumeContext / spawnContext.resume — per-node session re-attachment WITHIN one process) and the pre-existing durable Scope.resume (ResumedWork / scope.resume — cross-process restart from a journal). Both are surfaced on adjacent surfaces (a single spawn context could in principle carry both spawnContext.resume AND come from a scope.resume path). They are documented as distinct and operate at different la
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
Owner directive from #694: fresh respawns, session RESUMES, and live steers must all be expressible as plain data. This ships the axis.
continuity: 'fresh' | 'resume'(per-spawn override on the tool); every ledger row and journal edge event stamps the effective mode —fresh/resumeon spawns,steeron steer legs and analyzes deliveries. Zero ambiguity about how any hop continued.resume: { ofWorker, sequence }and owns session re-attachment; spend continuous in the one conserved pool; caps count resumes like spawns. Refused loud: no prior settled worker, prior still live (that's steer — the error says so), riding a semantic key, unresumable seams (workerFromBackendfails loud rather than ledger a resume that never happened — post-audit hardening). Resume after a FAILED prior is deliberately allowed (the seam decides salvageability) — tested and stated.examples/graphs/shot-loop-resumed.ts: the VB resumed-shot loop as pure data — shots stampfresh/resume/resume, lineage chain proven at the seam.Adversarially audited SHIP: lineage plumbing, dedup-distinctness, stamp integrity, refusals, and spend arithmetic all micro-revert-falsified; racing resumes proven safe (zero async gap).
0.127.0 + CHANGELOG. Suite 2364; typecheck/lint/build/docs/version-gate green.