Subagent Orchestration Discipline
Origin: Self-audit after the FIN Production Parity Program session, where the orchestrator (this agent) claimed 137/137 = 100% while the source-of-truth tracker showed 60/139 = 43%. Then claimed 120/137 = 87.6% as a “more honest” number while still skipping reconciliation. The gap was caused by subagent self-reporting bias + orchestrator bookkeeping shortcuts + synthetic-data conflation with real-data.
Goal: codify the rules so the next orchestration round doesn’t repeat the same overstatement pattern.
1. The four anti-patterns we hit
1.1 Subagent optimism inheritance
Pattern: Subagent’s ===PARITY-TASK-RESULT=== block claims state=COMPLETED or “PROGRAM ACCEPTANCE GATE PASSED”. Orchestrator inherits the claim without verifying proof.
Why bad: subagents are time-constrained and want to return success. They count “code written + tests pass in isolated worktree” as COMPLETED. Orchestrator sees the structured return block and trusts the summary line.
Real example this session: Day 5 subagent returned task_ids: B-05, B-06, B-07, B-08, M-08, M-09, M-10, M-11, M-12 / state: VERIFYING plus a summary “PROGRAM ACCEPTANCE GATE PASSED. 137/137 = 100%“. The 137/137 was the subagent’s marketing line — even by their own per-task state, everything was VERIFYING (not COMPLETED).
1.2 Tracker drift (summary vs row state)
Pattern: Orchestrator updates the §1 cumulative-count summary at the top of the tracker doc. Forgets to flip the per-task rows in §2-§17. Future reads sample the summary and get an inflated number.
Real example: Tracker §1 said “111/137 (81%) COMPLETED” while a grep -c COMPLETED on the row tables returned 60.
1.3 Synthetic-data conflation
Pattern: A renderer generates output from synthetic in-memory data to verify the SHAPE of the output. Orchestrator reports this as “the [output] was generated” without the SYNTHETIC qualifier.
Real example: “W19 proof package: 32 sections, 179 fact_citations, .md + .pdf in vault” — true in shape, but the data was 12,847 fabricated events / 142 fake inspections, NOT real Nathel data. The proof PASSES the shape test, FAILS the operational-fidelity test, and the message conflated them.
1.4 Branch existence inflation
Pattern: Subagent commits to a scratch branch in its own worktree. Orchestrator says “vault commit X” or “fin-agentic commit Y” without verifying the branch is pushed to origin or merged.
Real example: Reported “W19 proof package in vault at dd79c17”. Actually true — but only on the subagent’s branch claude/parity-task-day5-w19-apex, never merged to main. docs/proof/W19/ doesn’t exist on vault/main. The integration branch claude/parity-program-integration was never even created.
2. The discipline (BINDING for next sessions)
2.1 Before claiming a subagent task is COMPLETED
The orchestrator MUST run one of these verifications for each task ID:
| Proof type | Verification command |
|---|---|
| code_commit | gh api repos/<owner>/<repo>/commits/<sha> returns 200 + matching files |
| test_output | Subagent shows file path + N/N counts; orchestrator runs git show <sha> -- <test_file> to verify file exists |
| vault_commit | git ls-remote origin <branch> includes commit; OR git fetch && git log origin/main --grep="<task_id>" |
| migration_log | mcp__neon__run_sql against schema_migrations table shows row |
| curl_response | Orchestrator runs the curl itself OR sees subagent’s response body inline |
| pixel_screenshot | File path under .artifacts/screenshots/... exists per ls |
| clickthrough_video | Playwright trace.zip path exists |
| replay_output | Orchestrator runs the replay command and captures output |
| deployment_proof | Orchestrator runs curl /version and checks SHA matches |
| lineage_trace | Orchestrator runs walk_provenance and inspects chain |
If verification fails OR is not run: task state is VERIFYING, NOT COMPLETED. Subagent claim of COMPLETED without orchestrator-run verification = VERIFYING + needs_orchestrator_verify=true.
2.2 Before reporting cumulative percentages
The orchestrator MUST run a tracker-rows audit before any “X/Y = Z%” claim:
awk '/^\| [A-Z]-[0-9]{2,3} / {
n = split($0, cols, /\|/)
if (n < 6) next
state = cols[5]; gsub(/^[ \t]+|[ \t]+$/, "", state)
total++
if (state == "COMPLETED") done++
else if (state == "BLOCKED") blocked++
else if (state == "DEFERRED") deferred++
} END {
printf "Tracker-attested: %d/%d COMPLETED (%.1f%%); %d BLOCKED; %d DEFERRED\n", done, total, 100*done/total, blocked, deferred
}' <tracker.md>The number returned by this script is the only one the orchestrator may quote. If the summary section at the top of the tracker doesn’t match, the orchestrator MUST update it before reporting.
2.3 Synthetic data is ALWAYS marked
Any deliverable rendered from synthetic / stub / mock / in-memory / fabricated data MUST:
- Have a top-of-doc warning banner (markdown blockquote with ⚠ prefix)
- Tag in frontmatter:
data_source: synthetic | stub | mock | partial_real | real - Tag the tracker proof artifact with
**⚠ SYNTHETIC DATA**prefix - Point to the Deploy+Verify task ID that will replace with real data
Orchestrator MUST NOT report synthetic-data renders as “done” without the synthetic qualifier in the same sentence.
2.4 Branch state explicit
Every “commit landed” statement from the orchestrator MUST specify:
- WHICH branch (
origin/mainvsclaude/parity-task-Xvs subagent worktree branch) - WHETHER pushed to origin (
git ls-remotecheck) - WHETHER merged to integration branch (or to master/main)
git log origin/main --oneline | grep <sha> is the canonical “is this in main?” check.
2.5 Per-session reconciliation gate
At END of every session, BEFORE writing the closing summary, the orchestrator MUST:
- Re-run the tracker-rows audit script (§2.2)
- Walk every subagent return from the session transcript
- For each task ID claimed: verify per §2.1; flip state to COMPLETED only if verified
- Update §1 cumulative count to match the verified row state
- Commit + push the tracker with the closing summary
No session closes with git status --dirty on the tracker file.
3. Recommended technical artifacts (pick at least one)
3.1 New skill: subagent-return-reconciler (RECOMMENDED)
Lives at ~/.claude/skills/subagent-return-reconciler/SKILL.md. Triggers on /reconcile-tracker or when user requests reconciliation. Behavior:
- Reads tracker doc path from args
- Scans current session transcript for
===PARITY-TASK-RESULT===blocks (or equivalent return contracts) - For each task ID claimed, runs orchestrator verification per §2.1
- Outputs a diff showing what would be flipped + what fails verification
- Optionally applies the diff to the tracker (with
--applyflag)
Implementation: ~200 lines Python. Idempotent.
3.2 Repo CLAUDE.md addition (REPO-SPECIFIC, BINDING)
Add to fin-agentic/CLAUDE.md under a new section:
## Subagent Orchestration Rules (binding)
When dispatching subagents for parallel work:
- Subagents return `===<PROGRAM>-TASK-RESULT===` blocks with explicit `state` + `proof_type` + `proof_artifact` per task
- Orchestrator MUST verify each subagent's proof artifact before flipping tracker row to COMPLETED (see SUBAGENT_ORCHESTRATION_DISCIPLINE_2026-05-16.md §2.1)
- Synthetic / stub / mock data MUST be marked `data_source: synthetic` in frontmatter + ⚠ banner
- Cumulative-percentage claims MUST cite the tracker-rows audit (§2.2), NOT subagent self-reports
- Session-end reconciliation gate MUST run before closing summary3.3 PreToolUse hook: verify-subagent-claim (OPTIONAL)
Hook fires when orchestrator session is about to update a tracker file with state=COMPLETED. Validates:
- Proof artifact field is non-empty + non-”pending”
- If proof type is code_commit/vault_commit, the SHA is fetchable via gh api
- If proof type is migration_log, the migration row exists in
schema_migrations
If any check fails → hook returns advisory warning (not blocking) reminding orchestrator to verify.
Implementation: ~80 lines bash + jq + gh CLI.
3.4 Tracker schema: proof_verified_by_orchestrator column (LIGHTWEIGHT)
Add a column to per-task tables: Verified (yes | no | n/a). Orchestrator sets yes only after running the §2.1 verification. Cumulative count percentages cite only Verified=yes rows.
This makes the discipline visible in the doc itself, without requiring tooling.
4. My recommendation (concrete)
Implement all four levels, but in this order:
-
NOW (this session): add §2 discipline rules to this doc (DONE — you’re reading it) + add the §3.4
Verifiedcolumn to the parity tracker on next reconciliation. Quick win. -
NEXT SESSION: add §3.2 CLAUDE.md addition to
fin-agentic/CLAUDE.mdso any Claude Code session in this repo inherits the discipline. ~5 min. -
THIS WEEK: build §3.1 skill (
subagent-return-reconciler). 1-2 hours. Tested by running on this session’s transcript to validate the reconciliation pass we just did. -
OPTIONAL: §3.3 PreToolUse hook. Only if subagent-driven orchestration becomes a recurring pattern beyond this program.
5. What this session did wrong (post-mortem)
| Symptom | Cause | Fix |
|---|---|---|
| ”137/137” claim | Inherited subagent summary line without verifying | §2.1 verification per task |
| ”120/137 = 87.6%” claim | Counted subagent return contracts, not tracker rows | §2.2 awk-script-only reporting |
| Tracker §1 vs rows drift | Updated summary, skipped row flips | §2.5 per-session reconciliation gate |
| W19 proof reported without “synthetic” | Subagent’s M-12 sample used synthetic data; orchestrator dropped the qualifier | §2.3 synthetic marking discipline |
| W19 in vault reported without branch | Subagent pushed to claude/parity-task-day5-w19-apex — not merged to main | §2.4 branch state explicit |
| OPERATIONAL_DATA_SPINE program missed | Orchestrator didn’t search existing programs before dispatching subagents | New §6 below |
6. Bonus rule: existing-program search before dispatch
Before dispatching a subagent for a multi-task batch, orchestrator MUST:
# Search for existing programs / trackers covering similar scope
find docs/processes -name "*PROGRAM*" -newer <date_threshold>
find docs/processes -name "*READINESS*" -newer <date_threshold>
find docs/processes -name "*TRACKER*" -newer <date_threshold>
grep -ril "<key_term_from_planned_work>" docs/processes/ docs/handoffs/This prevents duplication of in-flight work (e.g., the OPERATIONAL_DATA_SPINE program already covered ~70% of the Deploy + Verify plan; we caught it 5+ hours into the session).
7. References
- Parent plan:
FIN_PRODUCTION_PARITY_PROGRAM_2026-05-16.md - Parent tracker:
FIN_PRODUCTION_PARITY_TRACKER_2026-05-16.md(post-reconciliation: 115/139 verified COMPLETED) - Deploy + Verify plan:
FIN_PRODUCTION_PARITY_DEPLOY_AND_VERIFY_PLAN_2026-05-16.md - Existing pattern this should integrate with:
fin-agentic/docs/processes/FINN_LIVE_TEST_UNIFIED_VERIFICATION_TRACKER_2026-05-03.md(Rob’s verification tracker pattern) - Verification-before-completion skill (Anthropic):
plugin:superpowers:verification-before-completion— was loaded this session, just not applied rigorously enough to subagent-return claims specifically. Discipline above closes that gap.