Skip to content

feat: commission native subagent dispatch to STANDARDIZED BOUNDED — follow-up to #356 - #358

Merged
sergstack merged 5 commits into
mainfrom
codex/native-subagent-dispatch-commissioning
Sep 2, 2026
Merged

feat: commission native subagent dispatch to STANDARDIZED BOUNDED — follow-up to #356#358
sergstack merged 5 commits into
mainfrom
codex/native-subagent-dispatch-commissioning

Conversation

@sergstack

Copy link
Copy Markdown
Owner

Summary

Owner decision: STANDARDIZE BOUNDED. This PR closes the commissioning punch-list (4/4), passes a two-round adversarial Judge review, and flips the status from STANDARDIZE BOUNDED (conditional) to STANDARDIZED BOUNDED — a bounded, pilot-scoped workflow, not a default/unrestricted standard.

No architecture change: no new router / state machine / DB / framework, no AES-record-schema change, no ROUTING_RULES change, no authority expansion, no child→child, no write-capable children.

Target standard:

root → bounded routed slice → Plan child + isolation:"worktree" → evidence/patch → root → validation / AES continuation

Punch-list — 4/4 closed

# Gap Closed by
1 deterministic dispatch-evidence schema + linter schemas/subagent_dispatch_evidence.schema.json + scripts/check_subagent_dispatch_evidence.py (schema + PROJECT_CAPABILITIES.yaml cross-check + acceptance gate) wired into .github/workflows/docs-safety.yml; tests/test_subagent_dispatch_evidence.py (15 tests)
2 mandatory per-dispatch telemetry schema requires duration_ms/subagent_tokens/tool_uses, each a number or the literal not_captured — a silent omission is a schema failure. Runtime emitted a usage footer for 1/18 dispatches (J2: 41801 tok / 15 tools / 84062 ms); the rest honestly not_captured
3 ≥15 hardened dispatches, ≥3 owners, required scenarios docs/evidence/subagent_dispatch_records_2026-09-02.json18 records, 7/7 owner capabilities, all Plan + isolation:"worktree": exec-commissionG (6-hop long multi-hop + repeat-route guard), exec-commissionH (2 deliberate failures + patch-return recovery), exec-commissionI (per-capability), exec-commissionJ (Judge), C-PROBE-1 (runtime re-verify). Guard-threshold population recorded with a proposalcontinuation.guards left unset, schema untouched
4 named cost/latency owner [AI OS], with a "when dispatch is justified vs inline root" rule, recorded in AGENT_LOOP_PLAYBOOK.md

Additional QA (owner-requested)

  • Exact no-nesting wording: "a Plan child cannot use the native Agent tool"; Bash-mediated external agent spawning = residual risk pending separate evidence (not observed in 18 dispatches).
  • Not claiming clean workspace 7/7: clean-tree recorded per record from each child's own git status; 18/18 reported clean.
  • Runtime re-verification (C-PROBE-1): Plan still has no Agent/Write; isolation:"worktree" still yields a clean linked worktree. A written bound now requires re-verification on any Claude Code runtime upgrade.

Code review

/code-review high — 5 findings, all fixed (e2ba3c2): acceptance gate no longer keyed only on free text (now also by filename); registry_executors() tolerates a missing executor block; missing jsonschema → distinct exit 2, not a spurious FAIL; dropped an unused import and an absolute local path; check_file returns (problems, doc) (no re-parse).

Judge review (adversarial)

  • Round 1 → revise (exec-commissionj J1): one blocking gap — the memo/status claimed the 2 deliberate-failure defects were "registered / in the AES defect lifecycle" with no FAILURE_REGISTRY.md entry (status inflation); def-/DEF- casing mismatched defect_ref.
  • Fix (7b1f2c4): IDs normalised to def-commission-h-001/002; language corrected — the induced failures are recorded in the dispatch-evidence JSON as outcome: refused + defect_ref, deliberate probes of the failure path, not FAILURE_REGISTRY.md/AES-lifecycle entries; those files stay unchanged.
  • Round 2 → pass (exec-commissionj J2): gap closed, no regression. judge_verdict: pass.

Acceptance (all yes) → status flips

deterministic isolated workspace proven · write child can't nest (removed) · runtime failure → recorded, honest, bounded recovery, no silent retry · 18 hardened dispatches with valid records (linter PASS, locked by a test) · long multi-hop keeps one execution_id + provenance · root-only router · Closure Review on original goal · no status inflation (round-1 fix) · scoped rollback · no authority expansion · Judge verdict = pass.

CURRENT_STATUS.md, MASTER_STATUS.md, docs/evidence/README.md, AGENT_LOOP_PLAYBOOK.md: STANDARDIZED BOUNDED. General/default promotion and the guard-threshold proposal each remain a separate owner decision.

Rollback

git revert the branch commits. New files (schemas/subagent_dispatch_evidence.schema.json, scripts/check_subagent_dispatch_evidence.py, tests/test_subagent_dispatch_evidence.py, the two evidence files) delete cleanly; the one-line docs-safety.yml step + wording edits revert in place; bundle + provenance revert together. No AES-schema migration, no runtime store, no .gitignore change.

Checks

6 canonical scripts + audit_bundle_provenance.py --check + check_subagent_dispatch_evidence.py + pytest tests/ -q (231 passed).

AES statuses

execution_state: completed · overall_delivery: pass · qa_status: pass · judge_verdict: pass · authority_status: owner_review_pending · merge_status: open · production_status: not_applicable

🤖 Generated with Claude Code

Claude Code and others added 4 commits September 2, 2026 15:39
…ry contract, 16-dispatch sample, cost owner

Closes the STANDARDIZE BOUNDED commissioning punch-list (4/4). No architecture
change: no new router/state-machine/DB/framework, no AES-schema or
ROUTING_RULES change, no authority expansion, no child->child, no
write-capable children.

1. schemas/subagent_dispatch_evidence.schema.json + scripts/check_subagent_dispatch_evidence.py
   (wired into .github/workflows/docs-safety.yml as a blocking step) +
   tests/test_subagent_dispatch_evidence.py (13 tests). Every executed
   dispatch must have a machine-checkable record: agent_type (Plan/Explore
   only), isolation "worktree", workspace observation under
   .claude/worktrees/agent-, execution/owner linkage, cross-checked against
   PROJECT_CAPABILITIES.yaml.
2. Telemetry contract: duration_ms / subagent_tokens / tool_uses are required
   keys, each a number or the literal "not_captured" (never omitted or
   invented). Runtime emitted no usage footer for the 16 commissioning
   dispatches -> all recorded not_captured, honestly.
3. docs/evidence/subagent_dispatch_records_2026-09-02.json — 16 hardened
   dispatches across all 7 owner capabilities:
   - exec-commissionG: 6-hop long multi-hop + repeat-route guard (bare repeat
     refused; repeat with evidence_delta allowed);
   - exec-commissionH: 2 deliberate failures (capability-missing write;
     missing-input read) both honest + registered (DEF-commissionH-001/002),
     no silent retry, plus a patch-return recovery the root applied;
   - exec-commissionI: per-capability coverage;
   - C-PROBE-1: runtime re-verification (Plan has no Agent/Write;
     isolation:"worktree" = clean linked worktree; unchanged).
   Guard-calibration population recorded with a proposal; the four
   continuation.guards remain unset (schema unchanged).
4. Cost/latency owner = [AI OS], with a "when dispatch is justified vs inline
   root" rule, recorded in AGENT_LOOP_PLAYBOOK.md.

QA: exact no-nesting wording ("a Plan child cannot use the native Agent tool";
Bash-mediated external spawn = residual risk pending separate evidence);
runtime-upgrade re-verify bound added.

Status stays STANDARDIZE BOUNDED (conditional) pending the Judge review;
flips to STANDARDIZED BOUNDED only on judge_verdict: pass.

Checks: 6 canonical + provenance + dispatch-evidence linter + pytest (229) pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ce linter

- acceptance gate now applies by filename match (subagent_dispatch_records*.json),
  not only when generated_for contains "commissioning" — a rename can no longer
  silently drop the >=15/owner/scenario enforcement;
- registry_executors() tolerates a capability with no executor block (degrades
  to {} -> clean FAIL message instead of an uncaught KeyError);
- missing jsonschema now raises a distinct EnvironmentError_ -> exit code 2
  ("CANNOT CHECK"), not a spurious validation FAIL (exit 1);
- check_file returns (problems, doc); main() no longer re-parses the file;
- tests: drop unused `import copy`; drop an absolute local path from a fixture;
  add coverage for the filename-based gate and the (problems, doc) return.

Checks: 6 canonical + provenance + dispatch-evidence linter + pytest (231) pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uage

Judge (adversarial) round 1 returned `revise`: the memo/status claimed the two
deliberate-failure defects were "registered / in the AES defect lifecycle" with
no FAILURE_REGISTRY.md entry or AES record — status inflation — and def-/DEF-
casing did not match `defect_ref`.

- IDs normalised to def-commission-h-001 / def-commission-h-002 in the JSON
  defect_ref, JSON notes, and the memo;
- language corrected: the two induced failures are recorded in
  subagent_dispatch_records_2026-09-02.json (outcome:refused + defect_ref) as
  deliberate probes of the failure-handling path, NOT FAILURE_REGISTRY.md
  regression cases; FAILURE_REGISTRY.md and the AES schema stay unchanged;
- acceptance table row 3 reworded to match.

Round-2 Judge re-review result folded in next.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…h to STANDARDIZED BOUNDED

Judge re-review (exec-commissionj J2, adversarial, Plan child in isolated
worktree, telemetry captured 41801 tok / 15 tools / 84062 ms): round-1 gap
closed, no regression on criteria 1/2/4/5/6. Verdict: pass.

- dispatch records: +J1 (round-1 revise) +J2 (round-2 pass) = 18 hardened
  dispatches across 7 owners; J2 is the first commissioning-campaign dispatch
  with a captured Agent usage footer;
- memo: Judge section filled from the observed result; counts 16 -> 18;
  telemetry capture status 1/18; §1 detail updated for the review fixes;
- status flipped conditional -> STANDARDIZED BOUNDED in CURRENT_STATUS.md,
  MASTER_STATUS.md, docs/evidence/README.md, and AGENT_LOOP_PLAYBOOK.md
  (bounded, pilot-scoped; NOT a default/unrestricted standard; general
  promotion + guard thresholds remain separate owner decisions).

judge_verdict: pass. No AES-schema / ROUTING_RULES / authority change; no
child->child; no write-capable children; rollback still a scoped git revert.

Checks: 6 canonical + provenance + dispatch-evidence linter + pytest (231) pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the needs-human-review Human review is required before merge label Sep 2, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Merge gate: protected paths changed. Auto-merge is disabled and owner review is required via CODEOWNERS.

…ceptance gate

Follow-up to the code-review fix in e2ba3c2: the module docstring still said the
acceptance gate keys only on `generated_for` containing "commissioning". It now
also applies by the `subagent_dispatch_records*.json` filename
(`acceptance_gate_applies`). Docstring only; no behaviour change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Merge gate: protected paths changed. Auto-merge is disabled and owner review is required via CODEOWNERS.

@sergstack
sergstack merged commit a7df97e into main Sep 2, 2026
2 checks passed
@sergstack
sergstack deleted the codex/native-subagent-dispatch-commissioning branch September 2, 2026 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human-review Human review is required before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant