feat(supervise): add recursive product control and durable identity - #657
feat(supervise): add recursive product control and durable identity#657drewstone wants to merge 13 commits into
Conversation
…gnal # Conflicts: # docs/api/primitive-catalog.md # docs/canonical-api.md # package.json # pnpm-lock.yaml # pnpm-workspace.yaml # tests/kernel/strategy-evolution.test.ts # tests/kernel/strategy-suite.test.ts
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 74b75602
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-07-29T19:08:15Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Concerns | 2 (1 low, 1 weak-concern) |
| Heuristic | 2.0s |
| Duplication | 0.0s |
| Interrogation | 260.0s (2 bridge agents) |
| Total | 262.0s |
💰 Value — sound
A coherent, grain-aligned unification: the supervisor becomes a full AgentProfile (killing the narrow special-case type), and every executed node gains durable content-addressed identity, materialization receipts, live root control, structured traces, and product authorization — completing patterns
- What it does: This PR (117 files, ~20.5k LOC, 0.109.2 → 0.110.0) does five concrete things. (1)
SupervisorProfilecollapses from a hand-rolled subset type ({ name, harness, model, systemPrompt }) intotype SupervisorProfile = AgentProfile; the supervisor's brain now resolves fromprofile.harnessexactly like a worker's executor (src/runtime/supervise/supervisor-agent.ts:69, `examples/supervise/supervi - Goals it achieves: Read from the code, the goal is to make the supervisor a first-class recursive agent — same profile, same materialization rule, same authorization surface as any worker — so product authority and traces can join a node to its backend across processes and hosts. This kills the parallel type surface (narrow
SupervisorProfilevs fullAgentProfile) that CLAUDE.md §1.5 explicitly outlaws, and it cl - Assessment: Sound and in the grain of the codebase. The unification is exactly what CLAUDE.md §1.5 (the 'AgentProfile law') prescribes — the supervisor stops being special. The materialization contracts are the structural counterpart to the already-shipped
validateAgentProfileSecurity(security axes vs behavioral axes, same fail-loud-before-compute shape). The durable identity events are additive kinds on t - Better / existing approach: Searched for an existing equivalent or a simpler design before answering. (a)
createRootHandleand theattachmachinery already existed insrc/runtime/supervise/supervisor.tson main (line 356 in the pre-PR version) — this PR extends them (addsdeliver, lease model, exports from/kernel), does not reinvent them. (b)validateAgentProfileSecurityalready existed for security axes — the n - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content
🎯 Usefulness — sound
Makes the supervisor a complete AgentProfile (the codebase's stated 'agent = full profile' law), exports the root control handle for live steering, and adds durable identity for same-host restart — all wired through the central supervise() front door with fail-closed materialization gating.
- Integration: Every new symbol has a caller. createRootHandle existed internally and is now exported from /kernel (src/runtime/index.ts:712); supervise() plumbs it via the rootHandle option (src/runtime/supervise/supervise.ts:1386) and attach() binds it to the live run. supervisorAgent() is constructed in exactly two places — root (supervise.ts:1341) and nested (supervise.ts:1281) — no competing construction. T
- Fit with existing patterns: Fits the grain exactly. CLAUDE.md §1.5 states 'an agent IS its full profile (prompt+skills+tools+mcp+subagents+hooks); you change behavior by AUTHORING the profile and letting the sandbox substrate materialize it — never write a verify-loop or harness-specific config.' Making SupervisorProfile a plain AgentProfile (supervisor-agent.ts:71) is the direct realization of that law. The root handle's de
- Real-world viability: Robustness is addressed beyond the happy path. The root handle moved from bind/unbind to an acquire/bind/release lease (supervisor.ts:775-803) so early-failure teardown releases cleanly (finally blocks at supervisor.ts:692-694). Resume path validates budget + identity + materialization match before continuing (supervisor.ts:132-171). New tests cover global concurrency (supervise-global-concurrency
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🔎 Heuristic Signals
🟡 Cruft: magic number added src/runtime/supervise/runtime.ts
seam.checkTimeoutMs ?? seam.harnessTimeoutMs ?? bridge.timeoutMs ?? 5 * 60 * 1000,
💰 Value Audit
🟡 Local spend helpers duplicated across 4+ files [duplication] ``
zeroSpendis defined in src/runtime/supervise/{driver-executor.ts:417, runtime.ts:260, scope.ts:2106} and src/durable/spawn-journal.ts:845;addSpendin driver-executor.ts:421 and supervisor.ts:1086;isNonZeroSpend/isNonEmptySpend(same shape, two names) in driver-executor.ts:435 and supervisor.ts:1100. Each is 3-15 lines and this PR added more copies. The canonicalspendFromUsageEventsalready lives in src/runtime/supervise/budget.ts; these small helpers could be co-located there (or i
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.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 162fea5a
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-07-29T19:27:58Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 2 (1 low, 1 weak-concern) |
| Heuristic | 2.2s |
| Duplication | 0.0s |
| Interrogation | 172.9s (2 bridge agents) |
| Total | 175.1s |
💰 Value — sound-with-nits
Upgrades the recursive supervisor into a product-control surface with trusted per-node identity, authorization hooks, durable/honest restart accounting, and provable execution-plan receipts — coherent and in the codebase's grain; one minor dead-interface wart.
- What it does: Makes
supervise()enforce and audit the repo's §1.5 'author the profile, the substrate materializes it' law. Every spawned node now carries a content-addressed NodeExecutionIdentity (profile+task+candidate digests via the sharedcanonicalCandidateDigest), a ProfileMaterializationReceipt (exact effective profile/backend/model/plan vs. what was authored), and per-attempt ExecutionBindingReceipts - Goals it achieves: Turn agent-authored recursive supervision into a trustworthy, auditable, product-controllable execution path: (1) model-authored metadata no longer decides driver-vs-leaf or spawn identity in isolation; (2) restart can't mint budget, slide deadlines, or silently treat unknown telemetry as zero; (3) a product can observe, steer, and cancel the live root and nested managers through one handle; (4) '
- Assessment: Strong, and firmly in the grain. It extends — not forks — the existing seams: the nested-scope seam key is reused (now with partitioned child pools),
contentAddresswas extracted tosrc/durable/content-address.tsand shared by trace-evidence, the profile-materialization contract system is broadened (sandboxActProfileMaterializationnow derives fromfullProfileMaterialization), and candidat - Better / existing approach: none — this is the right approach. I checked for an existing equivalent to reuse:
contentAddressis shared (not reimplemented),canonicalCandidateDigest/agentProfileSchemacome from@tangle-network/agent-interface, the recursive driver-executor and nested-scope seam are extended in place, andloadSpawnForestis genuinely new (the oldreplaySpawnTreeread only one tree). No partial dupl - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content
🎯 Usefulness — sound
A coherent, fully-wired capability that runs root and nested supervisors from complete AgentProfiles with durable identity and live root control — integrated into the main supervise() entry point and exercised by examples and ~8.6k lines of tests.
- Integration: Fully reachable. supervise() (supervise.ts:1343) is the primary consumer: it calls supervisorAgent() for root and nested supervisors, threads rootHandle via supervisor.attach() (supervise.ts:1388), wires authorizeDownMessage, and validates per-backend materialization contracts. createRootHandle is exported from /kernel (runtime/index.ts:712) and exposed as the rootHandle option on SuperviseOptions
- Fit with existing patterns: Follows the codebase grain precisely. supervisorAgent resolves the brain from profile.harness exactly mirroring createExecutor({backend}) resolving a worker (supervisor-agent.ts:495). The materialization contracts generalize the pre-existing per-path declaration pattern (sandboxActProfileMaterialization now aliases fullProfileMaterialization). Durable identity (rootIdentity, NodeExecutionIdentity,
- Real-world viability: Holds up under realistic use. A lease prevents two concurrent runs from racing one handle (supervisor.ts:776-803); the handle fails loud when unbound. The deadline timer is armed from an absolute clock captured before any async journal work, so a slow begin cannot extend the run on restart (supervisor.ts: runStartedAtMs). The resume contract asserts identity/budget/materialization match before reh
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🔎 Heuristic Signals
🟡 Cruft: magic number added src/runtime/supervise/runtime.ts
seam.checkTimeoutMs ?? seam.harnessTimeoutMs ?? bridge.timeoutMs ?? 5 * 60 * 1000,
💰 Value Audit
🟡 Dead RootSignal (pause/resume/ask) surface coexists with the operative deliver()/abort() on one public handle [maintenance] ``
The PR adds the real steering verb
SteerableRootHandle.deliver()and keepsabort(), butRootHandle.signal(msg: RootSignal)plus thepause/resume/askvariants remain on the public type with no handler anywhere (grep forcase 'pause'|'resume'|'ask'in src/runtime/supervise/ returns nothing). The PR body's 'Known limits' acknowledges these are 'non-operative legacy variants,' yet the interface still advertises them to callers. Two control surfaces on one handle, only one operative, is
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.
✅ No Blockers —
|
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 20 non-blocking findings — 162fea5a
Full multi-shot audit completed 8/8 planned shots over 117 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-07-29T20:04:23Z · immutable trace
Summary
AgentProfiles while binding product tools, spawn/message authorization, and awaited coordination transactions to trusted node identity.createRootHandlefrom/kernelso products can inspect, steer, and cancel the live root through the documented public API.AbortSignal, so caller, root, deadline, breaker, and recursive cancellation reach both router and external-MCP handlers.Verification
pnpm test— 2016 passed, 6 skipped across 188 passing and 2 skipped files.pnpm run typecheck— passed, including examples.pnpm run lint— 524 files checked.pnpm run docs:apiandpnpm run docs:check— passed with generated docs stable.pnpm run verify:package— passed, including build, package fixtures, static imports, export checks, and edge-safety checks.origin/mainmerge-tree — clean.Known limits
context.signal; JavaScript cannot forcibly interrupt an arbitrary in-process promise.rootHandle.deliver(...)and cancellation usesabort(...);RootSignalpause/resume/ask remain non-operative legacy variants.