@event4u/agent-config 9.28.0 → 9.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/AGENTS.md +6 -6
  3. package/CHANGELOG.md +172 -5
  4. package/README.md +2 -1
  5. package/agents/templates/.ai-council.yml.example +55 -24
  6. package/dist/agent-src/commands/analyze/inbox.md +22 -1
  7. package/dist/agent-src/commands/cost/report.md +2 -2
  8. package/dist/agent-src/commands/explain-run.md +31 -1
  9. package/dist/agent-src/commands/team/adversarial.md +8 -7
  10. package/dist/agent-src/commands/team/delegate.md +14 -12
  11. package/dist/agent-src/commands/team/review.md +9 -8
  12. package/dist/agent-src/commands/team/status.md +9 -8
  13. package/dist/agent-src/commands/team.md +29 -19
  14. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +88 -2
  15. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +29 -21
  16. package/dist/agent-src/contexts/execution/host-capability-manifest.md +26 -15
  17. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +22 -1
  18. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +17 -0
  19. package/dist/agent-src/contexts/execution/subagent-response-contract.md +65 -1
  20. package/dist/agent-src/contexts/execution/subagent-routing.md +13 -11
  21. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +25 -0
  22. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -3
  23. package/dist/agent-src/rules/delegation-policy.md +11 -7
  24. package/dist/agent-src/rules/preservation-guard.md +9 -0
  25. package/dist/agent-src/rules/settings-ask-protocol.md +8 -7
  26. package/dist/agent-src/rules/token-budget-discipline.md +1 -1
  27. package/dist/agent-src/scripts/roadmap_gates.ts +312 -0
  28. package/dist/agent-src/scripts/update_roadmap_progress.ts +72 -4
  29. package/dist/agent-src/skills/forensics-report/SKILL.md +114 -0
  30. package/dist/agent-src/skills/forensics-report/evals/triggers.json +17 -0
  31. package/dist/agent-src/skills/premortem/SKILL.md +30 -1
  32. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -1
  33. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +17 -5
  34. package/dist/agent-src/skills/subagent-orchestration/schemas/subagent-status.json +61 -3
  35. package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
  36. package/dist/agent-src/templates/AGENTS.md +4 -4
  37. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  38. package/dist/agent-src/templates/roadmaps.md +23 -0
  39. package/dist/cli/registry.js +2 -0
  40. package/dist/cli/registry.js.map +1 -1
  41. package/dist/cli-delegate/{chunk-22GCIJ2O.js → chunk-66OVWGB5.js} +1 -1
  42. package/dist/cli-delegate/{chunk-7OMQCH4V.js → chunk-BTJNRUX3.js} +22 -35
  43. package/dist/cli-delegate/{chunk-DVRS2KVR.js → chunk-DDUNNFYX.js} +24 -17
  44. package/dist/cli-delegate/{chunk-PQSAQKHW.js → chunk-EQY4FLJB.js} +3 -3
  45. package/dist/cli-delegate/{chunk-2BE5I2MN.js → chunk-IYTGIG2Y.js} +155 -91
  46. package/dist/cli-delegate/{chunk-GB2FSUEE.js → chunk-LCFJIQ4J.js} +32 -0
  47. package/dist/cli-delegate/{chunk-VSYT7OHO.js → chunk-LVRYBKTI.js} +31 -2
  48. package/dist/cli-delegate/chunk-MMJL4TIX.js +18 -0
  49. package/dist/cli-delegate/{chunk-JXARCGVN.js → chunk-MP3JT3IU.js} +1 -1
  50. package/dist/cli-delegate/chunk-O3CO5BFB.js +161 -0
  51. package/dist/cli-delegate/{chunk-REKCMYOU.js → chunk-PFBV6XRT.js} +36 -20
  52. package/dist/cli-delegate/chunk-RVGBH4XK.js +142 -0
  53. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  54. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  55. package/dist/cli-delegate/cmd_conformance.js +2803 -137
  56. package/dist/cli-delegate/cmd_doctor.js +10 -5
  57. package/dist/cli-delegate/cmd_explain.js +2 -2
  58. package/dist/cli-delegate/cmd_export.js +4 -4
  59. package/dist/cli-delegate/cmd_handoff.js +88 -8
  60. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  61. package/dist/cli-delegate/cmd_migrate.js +2 -2
  62. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  63. package/dist/cli-delegate/cmd_prune.js +4 -4
  64. package/dist/cli-delegate/cmd_route_audit.js +3 -2
  65. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  66. package/dist/cli-delegate/cmd_session_recycle.js +177 -0
  67. package/dist/cli-delegate/cmd_settings_get.js +2 -8
  68. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  69. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  70. package/dist/cli-delegate/cmd_sync.js +4 -4
  71. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  72. package/dist/cli-delegate/cmd_update.js +1 -1
  73. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  74. package/dist/cli-delegate/cmd_validate.js +4 -4
  75. package/dist/cli-delegate/cmd_versions.js +1 -1
  76. package/dist/discovery/deprecation-report.md +1 -1
  77. package/dist/discovery/discovery-manifest.json +72 -23
  78. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  79. package/dist/discovery/discovery-manifest.summary.md +3 -2
  80. package/dist/discovery/orphan-report.md +1 -1
  81. package/dist/discovery/packs.json +39 -2
  82. package/dist/discovery/trust-report.md +2 -2
  83. package/dist/discovery/workspaces.json +12 -4
  84. package/dist/hooks/dispatch.js +2278 -611
  85. package/dist/install/install.mjs +56 -17
  86. package/dist/mcp/registry-manifest.json +3 -3
  87. package/dist/mcp/server.json +2 -2
  88. package/dist/mcp/server.mjs +4122 -699
  89. package/dist/router.json +1 -1
  90. package/dist/scripts/_lib/agent_settings.js +54 -0
  91. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  92. package/dist/scripts/condense.js +147 -2
  93. package/dist/scripts/condense.js.map +1 -1
  94. package/dist/server/schemas/settings.js +12 -7
  95. package/dist/server/schemas/settings.js.map +1 -1
  96. package/dist/shared/settingsCarveOut.js +0 -9
  97. package/dist/shared/settingsCarveOut.js.map +1 -1
  98. package/dist/shared/settingsClasses.js +11 -9
  99. package/dist/shared/settingsClasses.js.map +1 -1
  100. package/dist/ui/assets/index-B5qGYOJo.js +26 -0
  101. package/dist/ui/assets/index-B5qGYOJo.js.map +1 -0
  102. package/dist/ui/index.html +1 -1
  103. package/docs/contracts/settings-classes.md +58 -12
  104. package/package.json +1 -1
  105. package/src/agent-src/scripts/roadmap_gates.ts +312 -0
  106. package/src/agent-src/scripts/update_roadmap_progress.ts +72 -4
  107. package/src/agent-src/templates/AGENTS.md +4 -4
  108. package/src/config/agent-settings.template.yml +88 -66
  109. package/src/config/discovery/packs.yml +11 -0
  110. package/src/config/discovery/workspaces.yml +1 -1
  111. package/src/config/dispatch-economy-metrics.json +61 -0
  112. package/src/config/evaluator-budgets.json +4 -4
  113. package/src/config/gate-violation-baselines.json +3 -3
  114. package/src/config/hook-token-budget.json +91 -0
  115. package/src/config/recycle-threshold-budget.json +12 -0
  116. package/src/config/rule-enforcement-baseline.json +86 -0
  117. package/src/scripts/_cli/cmd_conformance.ts +31 -44
  118. package/src/scripts/_cli/cmd_doctor.ts +65 -48
  119. package/src/scripts/_cli/cmd_session_recycle.ts +226 -0
  120. package/src/scripts/_dispatch.bash +23 -0
  121. package/src/scripts/_lib/agent_settings.ts +58 -0
  122. package/src/scripts/_lib/auto_dispatch.corpus.test.ts +1 -1
  123. package/src/scripts/_lib/auto_dispatch.ts +23 -18
  124. package/src/scripts/_lib/capsule_trigger.ts +124 -0
  125. package/src/scripts/_lib/host_capability.ts +63 -6
  126. package/src/scripts/_lib/judgment_ladder.ts +634 -0
  127. package/src/scripts/_lib/orchestration_gate.ts +8 -0
  128. package/src/scripts/_lib/orchestration_record.ts +78 -10
  129. package/src/scripts/_lib/orchestration_savings.ts +1 -1
  130. package/src/scripts/_lib/recycle_envelope_paths.ts +35 -0
  131. package/src/scripts/_lib/self_repair.ts +354 -13
  132. package/src/scripts/_lib/self_repair_store.ts +28 -0
  133. package/src/scripts/_lib/session_eol.ts +230 -0
  134. package/src/scripts/_lib/session_role.ts +42 -0
  135. package/src/scripts/_lib/subagent_capsule.ts +341 -0
  136. package/src/scripts/_lib/subagent_response.ts +94 -0
  137. package/src/scripts/_lib/subagent_spawn.ts +13 -0
  138. package/src/scripts/_lib/subagent_steering.ts +9 -4
  139. package/src/scripts/_lib/tier_budget_routing.ts +6 -1
  140. package/src/scripts/_lib/worker_budget.ts +37 -2
  141. package/src/scripts/ai_council/clients.ts +126 -55
  142. package/src/scripts/ai_council/config.ts +94 -6
  143. package/src/scripts/ai_council/handoff.ts +113 -0
  144. package/src/scripts/ai_council/modes.ts +19 -4
  145. package/src/scripts/ai_council/orchestrator.ts +105 -0
  146. package/src/scripts/ai_council/quorum.ts +84 -0
  147. package/src/scripts/ai_council/session.ts +44 -0
  148. package/src/scripts/ai_council/transport_resolver.ts +127 -1
  149. package/src/scripts/ai_team/availability.ts +110 -0
  150. package/src/scripts/ai_team/config.ts +34 -14
  151. package/src/scripts/ai_team/team_dispatch.ts +71 -29
  152. package/src/scripts/ask_transport.ts +221 -0
  153. package/src/scripts/bench_critic_protocol.ts +396 -0
  154. package/src/scripts/bench_hook_injection.ts +234 -0
  155. package/src/scripts/check_adr_frontmatter.ts +84 -40
  156. package/src/scripts/check_branch_freshness.ts +1 -0
  157. package/src/scripts/check_corpus_staleness.ts +18 -4
  158. package/src/scripts/check_detector_corpus.ts +219 -0
  159. package/src/scripts/check_gitignore_freshness.ts +42 -8
  160. package/src/scripts/check_hook_bundle_freshness.ts +24 -1
  161. package/src/scripts/check_kernel_prefix_stability.ts +1 -0
  162. package/src/scripts/check_standing_rule_delivery.ts +73 -32
  163. package/src/scripts/check_static_layer_stability.ts +154 -0
  164. package/src/scripts/check_suppression_hygiene.ts +48 -0
  165. package/src/scripts/condense.ts +162 -2
  166. package/src/scripts/council_cli.ts +401 -25
  167. package/src/scripts/dispatch_economy_report.ts +448 -0
  168. package/src/scripts/dispatch_r2_reviewer.ts +15 -2
  169. package/src/scripts/explain_run.ts +206 -4
  170. package/src/scripts/forensics_report.ts +333 -0
  171. package/src/scripts/generate_settings_reference.ts +1 -0
  172. package/src/scripts/handoff_context_hook.ts +112 -4
  173. package/src/scripts/hook_manifest.yaml +117 -10
  174. package/src/scripts/hooks/concern_registry.ts +8 -0
  175. package/src/scripts/hooks/delegation_nudge_hook.ts +106 -35
  176. package/src/scripts/hooks/dispatch_hook.ts +39 -2
  177. package/src/scripts/hooks/edit_shape_hook.ts +303 -0
  178. package/src/scripts/hooks/orchestration_record_hook.ts +19 -1
  179. package/src/scripts/hooks/reread_guard_hook.ts +314 -0
  180. package/src/scripts/hooks/rtk_wrap_hook.ts +133 -14
  181. package/src/scripts/hooks/session_eol_hook.ts +268 -0
  182. package/src/scripts/hooks/turn_end_gate_hook.ts +507 -0
  183. package/src/scripts/install-hooks.sh +1 -1
  184. package/src/scripts/language_mirror_hook.ts +89 -0
  185. package/src/scripts/lint_decision_impact.ts +14 -1
  186. package/src/scripts/lint_discovery_vocabulary.ts +2 -0
  187. package/src/scripts/lint_hook_manifest.ts +82 -0
  188. package/src/scripts/lint_never_silent.ts +276 -0
  189. package/src/scripts/lint_no_activation_gates.ts +271 -0
  190. package/src/scripts/lint_readme_serial_comma.ts +1 -0
  191. package/src/scripts/lint_rule_enforcement_declaration.ts +347 -0
  192. package/src/scripts/measure_turn_end_gate.ts +194 -0
  193. package/src/scripts/orchestration_record.ts +12 -1
  194. package/src/scripts/rebuild_hook_bundle.ts +178 -0
  195. package/src/scripts/release.ts +74 -2
  196. package/src/scripts/report_conformance_funnel.ts +284 -0
  197. package/src/scripts/report_imperative_density.ts +1 -0
  198. package/src/scripts/routing_doctor.ts +118 -36
  199. package/src/scripts/score_skill_selection.ts +19 -5
  200. package/src/scripts/self_repair_cli.ts +337 -59
  201. package/src/scripts/session_eol_report.ts +261 -0
  202. package/src/scripts/team_events_spike.ts +271 -0
  203. package/src/scripts/team_review_gate_hook.ts +31 -9
  204. package/src/server/schemas/settings.ts +24 -17
  205. package/src/shared/settingsCarveOut.ts +0 -10
  206. package/src/shared/settingsClasses.ts +11 -9
  207. package/src/templates/compact-instructions.md +40 -0
  208. package/dist/ui/assets/index-DmR0mbk4.js +0 -26
  209. package/dist/ui/assets/index-DmR0mbk4.js.map +0 -1
@@ -6,7 +6,7 @@ argument-hint: "[--background]"
6
6
  pack: meta
7
7
  tier: 2
8
8
  visibility: internal
9
- description: Thin wrapper — cross-model review of the current diff via the official plugin (/codex:review). Gated on ai_team.enabled; fails closed when the plugin is absent.
9
+ description: Thin wrapper — cross-model review of the current diff via the official plugin (/codex:review). Gated on /team availability (codex CLI + auth); fails closed when the plugin is absent.
10
10
  cluster: team
11
11
  sub: review
12
12
  suggestion:
@@ -26,11 +26,11 @@ Thin wrapper: cross-model review of the current change. On Claude Code hosts
26
26
  it delegates verbatim to the official plugin's `/codex:review` — this wrapper
27
27
  owns only the governance gates around it.
28
28
 
29
- ### 1. Gate — `ai_team.enabled`
29
+ ### 1. Gate — `/team` availability
30
30
 
31
- Read `ai_team.enabled` from `.agent-settings.yml`. Missing or `false` →
32
- print the enable pointer from `/team` (master) § "Default-off gate" and
33
- **STOP**. No plugin probe, no partial run.
31
+ Run the availability check from `/team` (master) § "Availability gate":
32
+ codex CLI + auth, and `emergency.orchestration_halt`. Either check fails →
33
+ print the matching block and **STOP**. No plugin probe, no partial run.
34
34
 
35
35
  ### 2. Gate — plugin presence (fail closed)
36
36
 
@@ -65,12 +65,13 @@ refusal, do not retry.
65
65
  ## Output format
66
66
 
67
67
  - The plugin's review, verbatim.
68
- - Nothing else on success; gate failures print exactly one block (enable
69
- pointer or fail-closed block) and stop.
68
+ - Nothing else on success; gate failures print exactly one block
69
+ (availability/halt block or fail-closed block) and stop.
70
70
 
71
71
  ## Do NOT
72
72
 
73
- - Do NOT run when `ai_team.enabled` is false — enable pointer, stop.
73
+ - Do NOT run when `/team` is unavailable (codex CLI/auth missing) or
74
+ halted — matching block, stop.
74
75
  - Do NOT reimplement the review inline when the plugin is absent — fail
75
76
  closed with the doctor pointer.
76
77
  - Do NOT edit files, commit, push, or open a PR — this wrapper is read-only.
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  pack: meta
6
6
  tier: 2
7
7
  visibility: internal
8
- description: Thin wrapper — plugin job status via /codex:status plus a quota block (shared openai counter vs team + council ceilings). Gated on ai_team.enabled; fails closed without the plugin.
8
+ description: Thin wrapper — plugin job status via /codex:status plus a quota block (shared openai counter vs team + council ceilings). Gated on codex CLI/auth availability; fails closed without the plugin.
9
9
  cluster: team
10
10
  sub: status
11
11
  suggestion:
@@ -25,11 +25,11 @@ Thin wrapper: team-mode status. On Claude Code hosts it delegates to the
25
25
  official plugin's `/codex:status` and appends **our** quota block —
26
26
  the one piece of state the plugin does not know about.
27
27
 
28
- ### 1. Gate — `ai_team.enabled`
28
+ ### 1. Gate — `/team` availability
29
29
 
30
- Read `ai_team.enabled` from `.agent-settings.yml`. Missing or `false` →
31
- print the enable pointer from `/team` (master) § "Default-off gate" and
32
- **STOP**.
30
+ Run the availability check from `/team` (master) § "Availability gate":
31
+ codex CLI + auth, and `emergency.orchestration_halt`. Either check fails →
32
+ print the matching block and **STOP**.
33
33
 
34
34
  ### 2. Gate — plugin presence (fail closed)
35
35
 
@@ -102,12 +102,13 @@ compatibility).
102
102
  ceilings + per-path OPEN/BLOCKED verdict).
103
103
  - Any `team.gate: BLOCK n/N` ledger lines, verbatim, after the quota
104
104
  block — only when present.
105
- - Gate failures print exactly one block (enable pointer or fail-closed
106
- block) and stop.
105
+ - Gate failures print exactly one block (availability/halt block or
106
+ fail-closed block) and stop.
107
107
 
108
108
  ## Do NOT
109
109
 
110
- - Do NOT run when `ai_team.enabled` is false — enable pointer, stop.
110
+ - Do NOT run when `/team` is unavailable (codex CLI/auth missing) or
111
+ halted — matching block, stop.
111
112
  - Do NOT fabricate a count when the counter file is unreadable — print
112
113
  `Quota: unavailable (<reason>)` instead of a guessed number.
113
114
  - Do NOT write to `cli-calls.json` — the transport owns the counter; this
@@ -15,7 +15,7 @@ type: orchestrator
15
15
  suggestion:
16
16
  eligible: true
17
17
  trigger_description: "second model, GPT drüberschauen lassen, cross-model review, review gate, let another strong model check the diff, team review"
18
- trigger_context: "ai_team.enabled is true AND the user wants a second strong model to review the actual working-tree diff with repo access (depth) — not a neutral artefact opinion (that is /council)"
18
+ trigger_context: "/team is available (codex CLI installed + authenticated, not halted) AND the user wants a second strong model to review the actual working-tree diff with repo access (depth) — not a neutral artefact opinion (that is /council)"
19
19
  workspaces:
20
20
  - agent-config-maintainer
21
21
  packs:
@@ -55,25 +55,33 @@ pre-registered benchmark (§ No-claims note).
55
55
  | Model choice | Mid-tier default (cost decision) | Strongest available — `ai_team.model: 'auto'` defers to the CLI default |
56
56
  | Write access | Never (text only; one opt-in PR comment under `pr`) | Read-only by default; `/team delegate` is the single write path, behind a second opt-in |
57
57
 
58
- ## Default-off gate — check FIRST, before anything else
58
+ ## Availability gate — check FIRST, before anything else
59
59
 
60
- Read `ai_team.enabled` from `.agent-settings.yml`. Missing key or `false`
61
- (the shipped default) → print the enable pointer and **STOP**. Do not route,
62
- do not suggest a sub-command, do not probe for the plugin:
60
+ `/team` carries no on/off setting — `ai_team.enabled` was REMOVED
61
+ (road-to-always-on-orchestration Phase 1, Step 1.3). Availability is a FACT
62
+ resolved from the machine: the codex CLI must resolve on `$PATH`, AND some
63
+ auth for it must be detectable (subscription login, API key, key file, or
64
+ env key) — the same check `agent-config doctor --check team` runs. Missing
65
+ either → print the degrade line and **STOP**. Do not route, do not suggest
66
+ a sub-command, do not probe for the plugin:
63
67
 
64
- > Team mode is disabled (`ai_team.enabled: false`, the default).
65
- > Enable it in `.agent-settings.yml`:
66
- >
67
- > ```yaml
68
- > ai_team:
69
- > enabled: true
70
- > ```
71
- >
72
- > Key reference: `docs/contracts/ai-team-config.md`. Then run
73
- > `agent-config doctor --check team` to verify plugin + auth setup.
68
+ > codex CLI not available — `/team` needs the codex CLI installed and
69
+ > authenticated. Install: `npm install -g @openai/codex`, then run
70
+ > `codex login`. Verify with `agent-config doctor --check team`.
71
+
72
+ Also check the one incident switch: `emergency.orchestration_halt: true`
73
+ in `.agent-settings.yml` halts `/team` along with the rest of the always-on
74
+ orchestration stack (subagents, council, team). Halted → print:
75
+
76
+ > `/team` is halted (`emergency.orchestration_halt: true`) — the always-on
77
+ > orchestration stack is paused for incident response. Resume: set
78
+ > `orchestration_halt: false` with a non-empty
79
+ > `orchestration_halt_justification` in `.agent-settings.yml`.
74
80
 
75
81
  Every sub-command repeats this check independently — the gate holds even when
76
- a wrapper is invoked directly.
82
+ a wrapper is invoked directly. A leftover `ai_team.enabled` key from an
83
+ older install is ignored (one deprecation-warning line on load) — it no
84
+ longer gates anything.
77
85
 
78
86
  ## Sub-commands
79
87
 
@@ -89,7 +97,8 @@ rather than routing to an in-suite skill — the second column names that target
89
97
 
90
98
  ## Dispatch
91
99
 
92
- 1. Run the default-off gate above. Disabled → enable pointer, stop.
100
+ 1. Run the availability gate above. Unavailable or halted → the matching
101
+ one-line block, stop.
93
102
  2. Parse the user's argument: `/team <sub-command> [args]`.
94
103
  3. Look up the sub-command in the table above; load the routed file and
95
104
  follow its `## Instructions` verbatim with the remaining args.
@@ -106,7 +115,7 @@ When the official plugin is absent on a Claude Code host, every wrapper
106
115
  fails **closed** with the doctor remediation pointer — never a silent no-op,
107
116
  never an inline reimplementation of the plugin:
108
117
 
109
- > ❌ Team mode is enabled, but the official plugin is not installed on this
118
+ > ❌ `/team` is available, but the official plugin is not installed on this
110
119
  > Claude Code host. `/team <sub>` fails closed — it never reimplements the
111
120
  > plugin inline and never silently no-ops.
112
121
  >
@@ -156,4 +165,5 @@ measured improvement.
156
165
  - `adversarial-review` skill — the free single-model first rung below
157
166
  `/team adversarial`.
158
167
  - `docs/contracts/ai-team-config.md` — the `ai_team` settings block
159
- (`enabled`, `model`, `allow_delegate`, `max_calls_per_day`).
168
+ (`model`, `allow_delegate`, `max_calls_per_day`) and the availability
169
+ contract (codex CLI + auth, `emergency.orchestration_halt`).
@@ -44,8 +44,10 @@ dwarfs the work). Below the floor → in-session.
44
44
 
45
45
  - Trivial / single-step edits below the size floor.
46
46
  - Tasks with cross-step shared mutable state that cannot be sliced.
47
- - Anything that fails to match a signal above → **no-op** (in-session),
48
- or **ask** when `subagents.auto == ask` and the shape is borderline.
47
+ - Anything that fails to match a signal above, once past the activation gate
48
+ and the size floor, is **ambiguous** → **ask**, always — a verdict to the
49
+ user, never a speculative spawn (always-on orchestration: there is no more
50
+ `subagents.auto` setting to route this on).
49
51
 
50
52
  ## Mode selection summary
51
53
 
@@ -55,6 +57,76 @@ dwarfs the work). Below the floor → in-session.
55
57
  | `parallelizable: files\|independent` / independent slices | `do-in-parallel` |
56
58
  | change needing verification (any of the above) | implementer + cross-model judge per the `subagent-orchestration` Iron Law |
57
59
 
60
+ ## Judgment ladder (Phase 2 — road-to-always-on-orchestration)
61
+
62
+ One committed table replacing three scattered classification surfaces
63
+ (the delegable-signal rules above, ad-hoc "should this be a team" calls,
64
+ and the absence of any council-routing signal on the task side). Resolver:
65
+ [`judgment_ladder.ts`](../../../../src/scripts/_lib/judgment_ladder.ts)
66
+ (`classifyLadder`) — a WRAPPER around `classifyTask`, never a replacement:
67
+ rungs 1 and 2 ARE `classifyTask`'s existing dispatch verdict.
68
+
69
+ | Rung | Shape signals | Resolves to |
70
+ |---|---|---|
71
+ | 0 | mechanical transform, no semantics (rename / codemod / formatter-run / bulk search-and-replace), OR a lookup-class match (§ Lookup-class rung above) | deterministic script, no spawn |
72
+ | 1 | single bounded read-heavy slice (`classifyTask` structurally cannot see this — it requires ≥2 slices, an ordered plan, or a declared `parallelizable` value) | one subagent, `lite` tier |
73
+ | 2 | enumerable independent slices, or an ordered plan (`classifyTask` dispatch: `do-in-parallel` / `do-in-steps` both land here in this v1 — see the resolver's doc comment for why) | parallel subagents, downshifted |
74
+ | 3 | slices that must communicate (cross-layer work, a review-with-challenge shape, an explicit shared task list) | team — only when the host reports `agent_teams: true`; else degrades to whatever `classifyTask` resolves on the same signals (usually rung 2), with a recorded `degraded_from: 3` line — never a fabricated slice count |
75
+ | 4 | judgment under disagreement (a design decision, a proposed security downgrade, a release-gate escalation) | council |
76
+ | ∅ | interactive-approval-required (caller-stated), trivial (below the size floor), or ambiguous | in-session; ambiguity is an `ask` VERDICT, never a speculative spawn |
77
+
78
+ ```
79
+ AMBIGUITY NEVER SPAWNS. RUNG 0 NEVER SPAWNS EITHER — IT NEVER NEEDED TO.
80
+ A MATCHED RUNG-3/4 SIGNAL WITHOUT ITS HOST PRECONDITION DEGRADES,
81
+ RECORDED — IT NEVER SILENTLY DROPS TO ∅.
82
+ ```
83
+
84
+ **Resolution order is fixed and documented on `classifyLadder` itself**:
85
+ interactive-approval-required → rung 0 → recursive-dispatch guard →
86
+ activation gate → rung 4 → rung 3 (+ degrade) → rungs 1/2. Two signals
87
+ matching the same text resolve deterministically on this order, never on
88
+ evaluation-order accident.
89
+
90
+ **Recursive-dispatch guard (2.3) — honest scope.** No verified host
91
+ discriminator exists for "is this classification running inside a
92
+ subagent/teammate session" — this roadmap's own `point-of-action-carrier`
93
+ blocker records the upstream PreToolUse agent-identity request as closed
94
+ NOT_PLANNED, and no field in this repo's hook envelope carries session
95
+ lineage. The guard is therefore a CALLER-SUPPLIED fact
96
+ (`insideSubagentSession`), never a `process.env` probe for an unverified
97
+ variable name — the same "no discriminator is publishable" null the
98
+ `point-of-action-carrier` blocker already names. When set, it resolves ∅
99
+ (in-session) for rungs 1-4; rung 0 is exempt (it never spawns).
100
+
101
+ **Relationship to the council's own necessity gate.** Rung 4's three
102
+ signals (design decision / security downgrade / release-gate escalation)
103
+ are a deliberately narrow, TASK-side vocabulary — NOT an import of
104
+ `ai_council/necessity.ts`'s broader `NECESSARY_TRIGGERS`
105
+ (architecture/tradeoff/ambiguity/strategic). That module stays the
106
+ council's own necessity gate (its `off|educate|block|warn-only` modes are
107
+ the council-side surface); this resolver only decides whether a TASK
108
+ should route to rung 4 in the first place.
109
+
110
+ ## Cheapest-sufficient-model table (Phase 2.4 — the ladder's tie-breaker)
111
+
112
+ Once a slice resolves to rung 1 or 2, this table is the tie-breaker
113
+ `classifyLadder`'s caller consults for the concrete tier — `lite` by
114
+ default, escalating only on a named criterion. Consolidates mechanisms that
115
+ already exist elsewhere in this contract set; this table is the ONE place
116
+ that lists them side by side.
117
+
118
+ | Escalation criterion | Tier | Basis |
119
+ |---|---|---|
120
+ | (none — default) | `lite` | the downshift default (`subagent-routing.md`) |
121
+ | Slice failed verification on its current tier | next tier up (`lite`→`medium`→`medium`→`high`) | [`subagent-steering`](subagent-steering.md) § Verify-fail escalation cascade |
122
+ | Slice touches ≥ 5 files (or > 200 lines) | `medium` | the ticket-bundle `lite` size floor (`docs/contracts/ticket-bundle-format.md`) |
123
+ | Architecture-shaped slice (structural/boundary decision — the same shape as rung 4's design-decision signal, one level down in stakes) | `medium` | [`subagent-modes-detail`](subagent-modes-detail.md) § Severity-conditioned team composition |
124
+ | Security-sensitive slice (auth, tenant, secrets, billing — `security-sensitive-stop`'s surface table) | `high` | [`subagent-modes-detail`](subagent-modes-detail.md) § Critical severity row |
125
+
126
+ Criteria are independent and additive in the obvious way (a slice matching
127
+ two rows takes the higher of the two tiers); this table never lowers a
128
+ tier `inferSliceTier` (§ below) already raised.
129
+
58
130
  ## Per-slice tier inference (v1.5 — deterministic, task-TYPE-keyed)
59
131
 
60
132
  Once a slice is classified **delegable**, a second deterministic table infers
@@ -174,8 +246,22 @@ and the lookup corpus in
174
246
  [`src/scripts/_lib/auto_dispatch.corpus.test.ts`](../../../../src/scripts/_lib/auto_dispatch.corpus.test.ts)
175
247
  (`LOOKUP_CORPUS` — the four live-observed shapes + negative controls).
176
248
 
249
+ The judgment ladder (§ above) is encoded in
250
+ [`src/scripts/_lib/judgment_ladder.ts`](../../../../src/scripts/_lib/judgment_ladder.ts)
251
+ (`classifyLadder`, plus the rung-0/1/3/4 signal-detection functions), covered
252
+ by
253
+ [`tests/scripts/_lib_judgment_ladder.test.ts`](../../../../tests/scripts/_lib_judgment_ladder.test.ts)
254
+ (every rung, the rung-3 degrade path, the recursive-dispatch guard, and every
255
+ ∅ case). The delegation-nudge hook
256
+ ([`delegation_nudge_hook.ts`](../../../../src/scripts/hooks/delegation_nudge_hook.ts))
257
+ is its first production caller — its injected line cites the resolved rung
258
+ (`rung-2: dispatch do-in-parallel …`), scoped to the subagent dispatch rungs
259
+ (1/2); a rung-0/3/4 verdict stays silent on this carrier until Phase 3/4 give
260
+ team/council their own.
261
+
177
262
  ## Related
178
263
 
179
264
  - [`auto-orchestration-activation`](auto-orchestration-activation.md) — the enable/auto/manifest gate that runs before classification.
180
265
  - [`subagent-orchestration`](../../skills/subagent-orchestration/SKILL.md) — the modes this selects.
181
266
  - [`autonomous-execution`](../../rules/autonomous-execution.md) — the N=3 budget any LLM-classification v2 must respect.
267
+ - [`orchestration-telemetry`](orchestration-telemetry.md) § Registered always-on metrics — the judgment-ladder precision metric this ladder feeds.
@@ -1,55 +1,62 @@
1
1
  # Auto-Orchestration Activation
2
2
 
3
- How the `subagents.*` keys in `.agent-settings.yml` resolve into automatic
4
- subagent dispatch at runtime. Companion to
3
+ How automatic subagent dispatch resolves at runtime. Companion to
5
4
  [`subagent-configuration`](../subagent-configuration.md) (which covers the
6
5
  model / parallelism keys) and
7
6
  [`host-capability-manifest`](host-capability-manifest.md) (which decides
8
7
  whether dispatch is physically possible on the host).
9
8
 
9
+ Always-on orchestration (road-to-always-on-orchestration, Phase 1): the layer
10
+ carries no per-run on/off setting. `subagents.enabled`, `subagents.auto`, and
11
+ `subagents.host_capabilities` were removed from `.agent-settings.yml` — a
12
+ fresh install with an empty settings file activates on any capable host.
13
+ Activation now reads only two facts: whether the emergency incident switch is
14
+ set, and what the host can physically do.
15
+
10
16
  ## Settings
11
17
 
12
18
  | Key | Default | Purpose |
13
19
  |---|---|---|
14
- | `subagents.enabled` | `true` | Global master switch. `false` = the whole layer is off — the canonical kill-switch. No auto-dispatch, no routing, everything runs in-session. |
15
- | `subagents.auto` | `on` | Auto-dispatch mode: `off` \| `ask` \| `on`. Shipped default `on` on subagent-capable hosts (flipped from `ask` 2026-07-09, ADR-117), `off` elsewhere. |
16
20
  | `subagents.downshift` | `true` | Route delegable sub-tasks to the lowest-capable tier (Phase 2). |
17
21
  | `subagents.quota_arbitrage` | `true` | Prefer a separate-quota-pool model where the host manifest allows it (Phase 2 bonus). |
18
22
  | `subagents.model_map` | `{}` | Optional per-tier model override for downshift routing. |
19
- | `subagents.host_capabilities` | `{}` | Optional override of the host-capability manifest. |
23
+ | `emergency.orchestration_halt` | `false` | The ONE audited incident switch — see [`settings-classes.md`](../../../../docs/contracts/settings-classes.md) § "The one exception". NOT an activation gate: on-by-default, ceremony-free to arm, requires a non-empty `orchestration_halt_justification` to disarm. |
20
24
 
21
25
  ## Activation decision
22
26
 
23
27
  For any task, auto-dispatch is attempted **only when all hold**:
24
28
 
25
29
  ```
26
- subagents.enabled == true
27
- AND subagents.auto != off
30
+ emergency.orchestration_halt != true
28
31
  AND host_manifest.subagent_spawn == true
29
32
  AND the task is classified delegable (see auto-dispatch-classification.md)
30
33
  ```
31
34
 
32
35
  If any condition fails → **in-session execution**, no subagent. This is the
33
- safe path: a missing/false manifest field, a disabled switch, or an
36
+ safe path: an unresolved host capability, an active incident halt, or an
34
37
  unclassifiable task all degrade silently to single-agent.
35
38
 
36
- ## `auto` mode behaviour
39
+ ## Verdict behaviour
37
40
 
38
- | Mode | When task is delegable | When not delegable |
39
- |---|---|---|
40
- | `off` | never dispatch (explicit command only) | in-session |
41
- | `ask` | ask once, then dispatch on yes (per `user-interaction`) | in-session |
42
- | `on` | dispatch; surface the chosen mode in one line | in-session |
41
+ | Task shape | Verdict |
42
+ |---|---|
43
+ | A matched delegable signal | `dispatch` — surface the chosen mode + per-subtask tiers in one line, never silent |
44
+ | No enumerated signal (ambiguous) | `ask` — a verdict to the user, never a speculative spawn |
45
+ | Below the size floor, halted, or no host primitive | in-session |
43
46
 
44
- Under `ask` and `on`, the chosen `subagent-orchestration` mode and the
45
- per-subtask tiers are surfaced before/at dispatch — never silent.
47
+ There is no more `off`/`ask`/`on` MODE setting driving this table — the row a
48
+ task lands on is a property of the task and the host, not a configuration
49
+ choice.
46
50
 
47
51
  ## Resolution order
48
52
 
49
- 1. Read `subagents.*` once per run; cache for the run (no re-read mid-loop),
53
+ 1. Resolve the emergency halt from settings once per run; cache for the run,
50
54
  mirroring [`subagent-configuration § When settings change`](../subagent-configuration.md).
51
- 2. Resolve the host-capability manifest once (cached) per
52
- [`host-capability-manifest`](host-capability-manifest.md).
55
+ 2. Resolve the host-capability manifest once (cached) via
56
+ `probeHostCapabilities` — the committed registry row merged with
57
+ observable environment facts. Per
58
+ [`host-capability-manifest`](host-capability-manifest.md), a settings
59
+ override no longer participates in production resolution.
53
60
  3. Apply the activation decision above per task.
54
61
 
55
62
  ## Safety floors are never lifted
@@ -57,8 +64,9 @@ per-subtask tiers are surfaced before/at dispatch — never silent.
57
64
  Auto-dispatch never bypasses a floor. The cross-model judge Iron Law
58
65
  (`subagent-orchestration`), `verify-before-complete`, the N=3 autonomous
59
66
  budget, `scope-control`, and `non-destructive-by-default` all apply to
60
- auto-delegated work exactly as they do to in-session work. `enabled: false`
61
- disables the layer; it never disables a floor.
67
+ auto-delegated work exactly as they do to in-session work.
68
+ `emergency.orchestration_halt: true` disables the layer for the duration of an
69
+ incident; it never disables a floor.
62
70
 
63
71
  ## Related
64
72
 
@@ -1,9 +1,9 @@
1
1
  # Host-Capability Manifest
2
2
 
3
- Resolved once per session by the **agent** (not a long-running process) and
4
- cached for the rest of the session. Tells the orchestration layer which
5
- subagent primitives the current host actually exposes, so auto-dispatch never
6
- attempts a primitive the host cannot run.
3
+ Resolved once per session (via `probeHostCapabilities`, not a long-running
4
+ process) and cached for the rest of the session. Tells the orchestration
5
+ layer which subagent primitives the current host actually exposes, so
6
+ auto-dispatch never attempts a primitive the host cannot run.
7
7
 
8
8
  ## Schema
9
9
 
@@ -15,19 +15,30 @@ A single JSON object, `schema_version: 1`:
15
15
  "subagent_spawn": false,
16
16
  "parallel_spawn": false,
17
17
  "status_polling": false,
18
- "separate_quota_pool": false
18
+ "separate_quota_pool": false,
19
+ "agent_teams": false
19
20
  }
20
21
  ```
21
22
 
22
23
  ## Resolution
23
24
 
24
- The agent fills the manifest from two inputs, in order:
25
+ `probeHostCapabilities(hostId)` (`src/scripts/_lib/host_capability.ts`) fills
26
+ the manifest from OBSERVABLE FACTS ONLY — capability is a fact about the
27
+ host, never a configuration decision (always-on orchestration, Phase 1):
25
28
 
26
- 1. The agent's own knowledge of the **current host** and its documented
27
- subagent primitives.
28
- 2. An **optional** settings override `subagents.host_capabilities` in
29
- `.agent-settings.yml`. Any field present there wins for that field; any
30
- field omitted falls back to the safe default below.
29
+ 1. The committed `HOST_CAPABILITY_REGISTRY` row for the detected host — the
30
+ agent's own knowledge of documented subagent primitives.
31
+ 2. A live environment probe merged on top: `agent_teams` resolves `true`
32
+ when `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` is set in the process
33
+ environment — the one host fact this repo can observe about Claude
34
+ Code's experimental multi-instance Agent Teams feature.
35
+ 3. `SAFE_DEFAULT` (all `false`) for an unrecognized host or an unset probe.
36
+
37
+ `resolveHostCapabilities(hostId, override?)` still accepts an optional
38
+ whole-object override for tests and back-compat callers, but no production
39
+ caller passes a settings-derived override into it any more — the former
40
+ `subagents.host_capabilities` settings key was removed. A leftover key in a
41
+ consumer's `.agent-settings.yml` is ignored.
31
42
 
32
43
  The manifest is resolved once and cached — the agent does not re-resolve it
33
44
  mid-session.
@@ -40,10 +51,9 @@ AN UNKNOWN HOST IS ASSUMED TO HAVE NO SUBAGENT PRIMITIVE.
40
51
  A MISSING OR INVALID FIELD IS false, NEVER true.
41
52
  ```
42
53
 
43
- This is a hard rule. When the host is unrecognized, or a field is absent /
44
- malformed in the override, the field resolves to `false`. The orchestration
45
- layer then degrades to in-session execution rather than attempting an
46
- unsupported primitive.
54
+ This is a hard rule. When the host is unrecognized, or a probed fact is
55
+ absent, the field resolves to `false`. The orchestration layer then degrades
56
+ to in-session execution rather than attempting an unsupported primitive.
47
57
 
48
58
  ## Fields
49
59
 
@@ -53,6 +63,7 @@ unsupported primitive.
53
63
  | `parallel_spawn` | bool | Concurrent dispatch of multiple subagents. `false` → delegation is serial, one subagent at a time. |
54
64
  | `status_polling` | bool | Monitoring running subagents (progress / completion checks). `false` → fire-and-collect only, no mid-run polling. |
55
65
  | `separate_quota_pool` | bool | Quota-arbitrage bonus (Phase 2) — subagents draw from a distinct quota pool than the session. `false` → assume shared quota. |
66
+ | `agent_teams` | bool | Claude Code's experimental multi-instance Agent Teams primitive (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`). `false` → the [judgment ladder](auto-dispatch-classification.md#judgment-ladder-phase-2--road-to-always-on-orchestration)'s rung 3 (team) degrades to parallel subagents, recorded as `degraded_from: 3`. |
56
67
 
57
68
  A field being `true` is a **precondition**, not a mandate: `parallel_spawn:
58
69
  true` permits concurrency but the dispatch cap still applies (see
@@ -59,13 +59,16 @@ v1 forward-compat rule on unknown fields).
59
59
  | `init_tokens` | int \| null | **Lean-init extension (road-to-lean-agent-init Phase 3).** Spawn-payload tokens at worker init — the payload-truth measurement feeding the Phase-5 baseline gate (p95 < ~1,500 tokens/worker drops the L2/L3 bets). `null` = not measured. Counts only. |
60
60
  | `payload_hash` | string \| null | **Lean-init extension.** 8–64-char hex digest of the spawn payload — prefix-stability / cache measurement. A hash can never smuggle content (privacy by construction). `null` = not measured. |
61
61
  | `lookup_class` | enum \| null | **Lean-init extension.** Lookup class the L0 rung matched: `definition` · `references` · `string-existence` · `report-run`. `null` = not a lookup-shaped dispatch. |
62
- | `route_taken` | enum \| null | **Lean-init extension.** `primitive` (deterministic primitive answered — no spawn) · `subagent` (escalated). With `lookup_class`, measures the tool-not-agent rung's hit rate. A `primitive` line is the ONE recordable zero-spawn event (`spawn_count: 0`) — the routing decision itself is the datum the cost claim reads. |
62
+ | `route_taken` | enum \| null | **Lean-init + dispatch-economy extension.** `primitive` (deterministic primitive answered — no spawn) · `ask` (rung-0.5 single completion via `ask_transport`, no session) · `subagent` (escalated). With `lookup_class`, measures the tool-not-agent rung's hit rate. `primitive` and `ask` lines are the TWO recordable zero-spawn events (`spawn_count: 0`) — the routing decision itself is the datum the cost claim reads. |
63
63
  | `budget_hit` | bool \| null | **Lean-init extension.** Worker hit its `max_tokens_per_worker` stop-loss (L0b) and returned the structured partial result. Feeds budget-seed refinement. `null` = not measured. |
64
64
  | `correctness_match` | bool \| null | **Lean-init extension.** Golden/correctness comparison verdict for a primitive route (primitive answer ≡ agent answer). Populated only when a comparison arm actually ran (bench/golden mode); on real zero-spawn primitive routes there is no agent answer to compare against, so `null` is the NORMAL field value — never read `null` as "unchecked = suspicious". |
65
65
  | `cache_hit` | bool \| null | **Lean-init extension (Phase 4 prefix stability).** Provider-reported prompt-cache hit on the spawn payload. Measurement only — no savings claim without provider-response evidence. `null` = not measured. |
66
66
  | `origin` | string \| null | **Lean-init extension (council Q5 segregation).** Id-shaped sample tag (`lean-init-2026`) keeping lean-init efficiency lines cleanly separable from the `road-to-orchestration-scope-decision` sample. `null` = untagged line. Never free-form. |
67
67
  | `rules_carried` | int \| null | **Lean-init extension (L6 demand signal).** Rules in the worker's scoped projection — the carried set. With `rules_used`, yields the per-worker rule-usage quota the parked `later/road-to-deferred-rule-retriever` resume condition asks for ("are worker rules actually carried unused?"). `null` = not measured. Counts only. |
68
68
  | `rules_used` | int \| null | **Lean-init extension (L6 demand signal).** Rules the worker actually applied/cited. Validation: never exceeds `rules_carried`. `null` = not measured. Counts only. |
69
+ | `work_tokens` | int \| null | **Dispatch-economy extension.** Tokens the worker consumed AFTER init — the delta from first worker turn to envelope close. With `init_tokens`, yields the `dispatch_floor` ratio (`src/config/dispatch-economy-metrics.json`). Sourced from the transcript ledger (`_lib/cc_transcript.ts` `billable_input` semantics) by the report/backfill, never model-estimated without the tag below. `null` = not measured. |
70
+ | `floor_provenance` | enum \| null | **Dispatch-economy extension.** Provenance of the `init_tokens`/`work_tokens` pair: `measured` (transcript ledger) · `estimated`. Auto-defaults to `estimated` when either field is present untagged — mirrors `token_delta_provenance`. `null` = neither field present. |
71
+ | `return_channel_chars` | int \| null | **Dispatch-economy extension (Phase 6.3).** Serialized chars of the tool result returned into the orchestrator context (sync completions, hook-derived count — content never enters the record). Detector for "isolation win refunded through the return channel"; committed cap: `MAX_ENVELOPE_CHARS` (12,000) via `return_channel` in `dispatch-economy-metrics.json`. `null` = async ack. |
69
72
 
70
73
  These routing + cost fields are additive and optional — a line without them is
71
74
  still a valid orchestration line; readers ignore unknown fields per the v1
@@ -216,6 +219,24 @@ condition outright. No consumer of `payload_hash` or `cache_hit` may wire a
216
219
  measure→adjust step off them — no default flip, no tier change, no dispatch
217
220
  throttle. They are read-only diagnostic fields.
218
221
 
222
+ ## Registered always-on metrics and kill criteria (pre-registered 2026-08-09)
223
+
224
+ The always-on orchestration doctrine fixes "the stack is always available"
225
+ and moves falsifiability into its TRIGGERS. Registered before any behaviour
226
+ data existed, so later readings cannot be fitted to a desired outcome:
227
+
228
+ | Metric | Source | Kill/tighten criterion (per layer, applied by evidence-bearing PR, never a settings flag) |
229
+ |---|---|---|
230
+ | Dispatch rate per delegable verdict | `orchestration_record` vs nudge/ladder verdict lines | A layer whose verdicts are measurably ignored gets its trigger set tightened or the injected line removed |
231
+ | Judgment-ladder precision (verdict vs what the session did) | ladder verdict telemetry joined with dispatch/team records | A rung below registered precision at review gets its signal set tightened; a rung nobody hits gets removed |
232
+ | Council fire rate + unactioned-verdict rate | pass artifacts + handoff adoption | Unactioned-verdict rate is the kill criterion for any auto-fire trigger |
233
+ | Per-session quota burn per provider | transport/attendance records | Sustained quota exhaustion tightens `cli_call_budget` defaults, never re-introduces an activation gate |
234
+ | Metered-fallback spend | billing-classified transport records | Target trends to ~0 on CLI hosts; a rising trend is a transport-resolution defect to fix, not a reason to disable |
235
+
236
+ Review discipline: each criterion is evaluated against an accumulation
237
+ window (the gated blockers name their own windows); a reading below the bar
238
+ removes or tightens THE TRIGGER, and the removal PR cites the numbers.
239
+
219
240
  ## Related
220
241
 
221
242
  - [`audit-log-v1`](../../../../docs/contracts/audit-log-v1.md) — the frozen
@@ -203,6 +203,23 @@ For each open step in the working set (scope-bound — see wrapper):
203
203
 
204
204
  Anti-pattern: `view step` → think → `view file A` → think →
205
205
  `view file B`. That's 3 round-trips for what should be 1.
206
+
207
+ Fire/no-fire pair (falsifiable — the discriminator is whether a
208
+ call's *input* depends on another call's *output*, never the count):
209
+
210
+ - **Fires (batch these):** a step says "update the hook, its test,
211
+ and the manifest entry" → `view src/scripts/hooks/foo_hook.ts` +
212
+ `view tests/scripts/foo_hook.test.ts` +
213
+ `view src/scripts/hook_manifest.yaml` are three independent reads
214
+ whose paths are all known BEFORE the first call — dispatch all
215
+ three in ONE parallel block. Issuing them serially is the
216
+ violation: each extra round-trip re-transmits the accumulated
217
+ context as input for zero new information.
218
+ - **Does NOT fire (stays serial):** `grep -rn "buildAdvisoryLine"
219
+ src/` → then `view <the file the grep found>`. The second call's
220
+ path IS the first call's output — batching would mean guessing the
221
+ path, and a guessed read is worse than a round-trip. Dependent
222
+ calls stay serial; only the independent remainder batches.
206
223
  2. Analyze the codebase for what the step requires.
207
224
  3. Decide and act — implement. **No "should I implement this?" prompt.**
208
225
  4. **Open question handling:**
@@ -13,13 +13,23 @@ orchestrator synthesises and re-verifies.
13
13
  "findings": [{ "title": "", "evidence_refs": ["file:line | id | path"], "mutating": false }],
14
14
  "risks": [],
15
15
  "confidence": "low | medium | high",
16
- "handoff": ""
16
+ "handoff": "",
17
+ "artifact_paths": ["<runtime artifact dir path — where the FULL result lives on disk>"]
17
18
  }
18
19
  ```
19
20
 
20
21
  - **Refs, not bodies.** `evidence_refs` are ref tokens (`file:line`, ids, paths),
21
22
  never inline content — same minimal-slice / privacy floor as the spawn contract.
22
23
  - `mutating` marks a finding whose action changes files/state (feeds the verify link).
24
+ - **The envelope is the ONLY return channel** (token-economy-dispatch Phase 6):
25
+ a worker's full result lands on disk (runtime artifact dir, gitignored) and
26
+ `artifact_paths` names where; the orchestrator consumes from those paths on
27
+ demand, never via wholesale transcript ingestion. Committed size caps,
28
+ validator-ERRORED (never silent truncation): `summary` ≤ 2,000 chars ·
29
+ line-shaped fields (`handoff`, a risk, a finding title) ≤ 240 · arrays ≤ 40
30
+ entries · one artifact ref ≤ 200 · the whole serialized envelope ≤ 12,000
31
+ chars (~3k tokens against a measured ~251k spawn floor). Constants + checks:
32
+ `src/scripts/_lib/subagent_response.ts`.
23
33
 
24
34
  ## Budget-hit partial result
25
35
 
@@ -41,6 +51,60 @@ refs-not-bodies floor as `evidence_refs`. Validator:
41
51
  `worker_budget.validateWorkerPartialResult` — the orchestrator never adopts an
42
52
  invalid partial return.
43
53
 
54
+ ## Stated assumptions — `assumptions[]`
55
+
56
+ Both the result body above and the CHECKPOINT capsule below may carry:
57
+
58
+ ```json
59
+ { "statement": "<one line>", "basis": "<ref token>", "epistemic_state": "verified | assumed | gap" }
60
+ ```
61
+
62
+ The vocabulary is the **Evidence-Report buckets** from
63
+ [`evidence-discipline`](evidence-discipline.md#evidence-report--the-discovery-output)
64
+ — pinned once, in `subagent_capsule.EPISTEMIC_STATES`, and deliberately not a
65
+ private scale: a capsule that graded its premises differently from the rest of
66
+ the suite would fork the vocabulary every other surface reasons in.
67
+
68
+ Absent `assumptions[]` means **not recorded** — never "no assumptions were
69
+ made". Unstated premises are the first thing compression drops, which is
70
+ exactly why the field exists on the handoff surface.
71
+
72
+ ## CHECKPOINT capsule — the generation handoff
73
+
74
+ `CHECKPOINT` is the fifth envelope status. A worker that reaches its budget
75
+ **watermark** (below the stop-loss line, so it still has the headroom to
76
+ summarise itself) returns a capsule instead of running on to be killed:
77
+
78
+ ```json
79
+ {
80
+ "status": "CHECKPOINT",
81
+ "summary": "<one or two sentences>",
82
+ "generation": 1,
83
+ "done": ["file:line | id | path"],
84
+ "remaining": ["<one short line each>"],
85
+ "decisions": ["<choices the successor must not silently re-open>"],
86
+ "open_risks": ["<still open at handoff>"],
87
+ "touched_files": ["path | file:line"],
88
+ "assumptions": [{ "statement": "", "basis": "", "epistemic_state": "verified" }]
89
+ }
90
+ ```
91
+
92
+ **Transcript-exclusion by construction.** Every field is a ref token, a single
93
+ short line, or a count; array entries are capped so a transcript cannot be
94
+ reached by accumulation either. There is no field a raw transcript fits in —
95
+ and that is load-bearing, not stylistic: the claim under test is whether a
96
+ successor can work from the *capsule*, which is unmeasurable the moment raw
97
+ context can ride along. Validator:
98
+ [`subagent_capsule.validateCapsule`](../../../../src/scripts/_lib/subagent_capsule.ts);
99
+ the orchestrator never briefs a successor from an invalid capsule.
100
+
101
+ **Status today: additive and off.** Nothing reads a capsule. Emission is
102
+ shadow-only (the worker still runs to stop-loss exactly as before) and the
103
+ synthesis duties below have no `CHECKPOINT` branch, so the measurement is not
104
+ confounded by the mechanism it is measuring. The recycling loop that consumes a
105
+ capsule is gated behind `blocker: host-worker-respawn` and
106
+ `blocker: capsule-quality-near-budget`.
107
+
44
108
  ## Orchestrator synthesis duties
45
109
 
46
110
  ```