fix(supervisor-run): preserve recursive source semantics - #485
Conversation
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 6f29632a
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-29T17:28:13Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 126.1s (2 bridge agents) |
| Total | 126.1s |
💰 Value — sound-with-nits
Makes the supervisor-run analyzer correct for nested (supervisor-of-supervisor) trees by joining workers on stable IDs and scoping retry/reaction metrics per-parent, plus splits token/deliverable channels into independent unavailable-vs-zero reasons — coherent and in-grain; only nit is committed tra
- What it does: The analyzer previously assumed a flat one-root-spawns-workers tree. This change (1) joins worker logs by stable
workerIdwithlabelonly as a legacy fallback (analyze.ts:216-218, 328, 414), so duplicate human labels under different supervisors no longer overwrite each other's facts; (2) computesrespawns,observeThenRespawn,respawnWithoutEvidence, andrepeatedLabelsgrouped by direct - Goals it achieves: Make reports correct for RECURSIVE runs the module already claimed to model (it had
delegationDepthand the claude-code reader already discovered nested spawns at claude-code-reader.ts:386-390, but mis-analyzed them). After merge: identical worker labels in sibling branches stay distinct; 'retry'/'respawn' mean what one supervisor did, not what happened anywhere; an uncaptured token channel repo - Assessment: Strong, in-grain correctness fix. It extends the module's load-bearing
Measured<T>/ unavailable-≠-zero discipline (types.ts:38-54) precisely where it was leaking fabricated zeros, and the parent-local grouping is the only semantically correct scope for retry/respawn — those are inherently per-supervisor decisions. It reuses the singleparseSupervisorTreeparser (one parse, two consumers: anal - Better / existing approach: none — this is the right approach. I checked for an existing tree/grouping utility to reuse:
src/rollout/mint.tsandschema.tstreatparent_rollout_idas a flat row field with no tree-traversal helper, and no shared parent→children index exists anywhere in src/. ThechildSpawnsByParentmap (analyze.ts:490-496) is built inline and used once; extracting a 'tree node' abstraction would fight - 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
Fixes two real correctness bugs in recursive supervisor-tree analysis (global respawn accounting contaminating sibling branches, and label-keyed worker joins merging unrelated workers) plus closes a fabricated-zero loophole by splitting manager/worker token channels in SourceLimits.
- Integration: Fully reachable and exercised. Both readers populate the new fields: loops-reader extracts workerId from the started event (loops-reader.ts:99-104) and declares workerTokens unavailable when the harness join fails (loops-reader.ts:186-189); claude-code-reader sets workerId=agentId per spawn (claude-code-reader.ts:567) and emits role on every journal line (claude-code-reader.ts:462). The analyzer (
- Fit with existing patterns: Matches the module's central patterns exactly. (1) The Measured unavailable-vs-zero discipline (types.ts:38-39) is the module's load-bearing invariant; adding managerTokens/workerTokens to SourceLimits extends it to token channels that previously fabricated zeros when a harness join failed — directly aligned with CLAUDE.md's 'No fallbacks. Fail loud.' doctrine. (2) The source-agnostic reader co
- Real-world viability: Holds up on the path it targets. The parent-local respawn accounting (analyze.ts:502-533) correctly scopes labelCounts, orderedSpawns, and directCloseTimes per-parent, so two supervisors each spawning 'same task' no longer cross-count — proven by analyze.test.ts:391-490. The workerId ?? label fallback (analyze.ts:216-218, rollout-nodes.ts:228) keeps legacy label-keyed stores working. readVerdict (
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
💰 Value Audit
🟡 Transient agent-run artifacts committed into the source tree [maintenance] ``
The diff adds
.agent/critical-audit/2026-07-29T17-08-06Z/{findings.jsonl,manifest.json,summary.md},.agent/skill-runs.jsonl.findings.jsonlis empty, the manifest has placeholder reviewers ["A","B","C"] and head "working-tree" — clearly throwaway run metadata, not package content..gitignoredoes not exclude.agent/(only.marketing-agent-runs/), so these will accumulate across PRs. Recommend adding.agent/to.gitignoreand dropping these files from the PR; they are not part of
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 — 10 non-blocking findings — 6f29632a
Full multi-shot audit completed 5/5 planned shots over 18 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-29T17:41:35Z · immutable trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — e1f37fd4
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-29T18:48:26Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Concerns | 0 (none) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 103.0s (2 bridge agents) |
| Total | 103.0s |
💰 Value — sound
Fixes the supervisor-run analyzer so recursive (multi-level) supervision trees are accounted correctly: parent-local retry/repeated-label counting, stable workerId joins, structured verdict preservation, and explicit independent token-availability declarations — all additive and in-grain.
- What it does: Extends the supervisor-run module to correctly model recursive supervision trees. (1) Worker logs now join to journal spawns by stable
workerIdfirst, falling back to label only when no id exists (workerSourceKey, analyze.ts:216-218), so two workers sharing a label under different supervisors no longer merge. (2) Respawns, repeatedLabels, observeThenRespawn, and respawnWithoutEvidence are now co - Goals it achieves: Correctness for real recursive supervision trees where supervisors spawn sub-supervisors that spawn workers and the same task label recurs across branches — the prior global accounting fabricated retries and repeated-labels that were cross-branch coincidences, not real supervisor decisions. Secondary goal: align the module with the repo's fail-loud doctrine by replacing fragile null/0 inference (w
- Assessment: A coherent, well-grained fix that extends the existing architecture rather than restructuring it. The analyzer stays pure and source-agnostic; readers (loops-reader, claude-code-reader) populate the enriched contract. All contract changes are additive and backward-compatible: workerId and role are optional on WorkerLogSource/spawned-events for legacy sources, and NO_SOURCE_LIMITS defaults both new
- Better / existing approach: none — this is the right approach. I searched for existing verdict/role/token-availability handling to reuse: src/verdict.ts holds DefaultVerdict (a training-gate type, not journal parsing); src/rollout/reward.ts exports unscreenedRewardFields (already reused in rollout-nodes.ts:163,260); src/rollout/readers/claude-jsonl.ts owns transcript parsing (already reused via parseClaudeEntries in claude-c
- 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 correct, well-wired fix that makes recursive supervisor-tree accounting parent-local and adds independent token channels, immediately consumed by both readers and the rollout-row minter.
- Integration: Fully wired and reachable. Both production readers (loops-reader.ts:116-121, claude-code-reader.ts:454-466) populate the new fields (workerId, role, structured verdicts, managerTokens/workerTokens limits). The rollout-row minter (rollout-nodes.ts:243-272) consumes spawn.role, close.valid/score/rawVerdict. The new type is exported (src/index.ts:549) and the public contract is locked by index.test.t
- Fit with existing patterns: Fits the codebase's established patterns exactly. The SourceLimits extension (independent managerTokens/workerTokens) is the natural continuation of the existing spendUsd/workerVerdicts/deliverables model. The workerSourceKey = workerId ?? label preserves the legacy label-join as a documented fallback, matching the backward-compat posture already taken for WorkerLogSource.workerId being optional.
- Real-world viability: Holds up under the edge cases that motivated it. The parent-local respawn/label accounting is verified against fixtures with identical labels under two different supervisors (no false merge) and same-label retries under one parent (correctly counted). Structured verdict parsing handles string, object, and null inputs. The reader's worker-id recovery requires unanimous agreement across started rows
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
No concerns — sound change, no better or existing approach found. ✅
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 — 3 non-blocking findings — e1f37fd4
Full multi-shot audit completed 5/5 planned shots over 19 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-29T18:57:45Z · immutable trace
What changes
workerIdidentity from Claude and loops journals so duplicate worker labels no longer merge unrelated branches.agent-eval; source readers consume their own journal contracts.Consumer migration
Every custom
SourceLimitsobject literal must addmanagerTokensandworkerTokens. Set a field tonullonly when that role's aggregate token channel is complete; otherwise set a reason string.NO_SOURCE_LIMITSalready includes both fields.WorkerLogSource.workerIdand spawned-eventroleremain optional for legacy sources. Duplicate labels require stable IDs for unambiguous joins. Report fields are additive: steer/per-worker rows now exposeworkerId, and per-worker rows exposeroleandscore.Proof
pnpm test: 312 files passed, 2 skipped; 4,222 tests passed, 3 skipped.pnpm typecheck: passed.pnpm typecheck:examples: passed.pnpm lint: 572 files checked, passed.pnpm build: package and OpenAPI builds passed.pnpm verify:package: skills check, publint, package exports, and accepted ESM declaration profiles passed.supervisor-rundeclarations exportSupervisorRunNodeRole; builtNO_SOURCE_LIMITScontains independent manager/worker token channels.git merge-tree --write-tree origin/main HEAD: succeeded (3995ad6ef1319f8e09c8753114777932ee90d0f2).