@event4u/agent-config 16.0.0 → 16.1.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 (246) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +297 -137
  5. package/CONTRIBUTING.md +9 -0
  6. package/README.md +2 -2
  7. package/dist/agent-src/commands/analyze/inbox.md +26 -0
  8. package/dist/agent-src/commands/analyze/roadmap-repos.md +27 -0
  9. package/dist/agent-src/commands/challenge-me/closure.md +178 -0
  10. package/dist/agent-src/commands/challenge-me.md +9 -2
  11. package/dist/agent-src/commands/council/default.md +25 -5
  12. package/dist/agent-src/commands/feature/plan.md +28 -1
  13. package/dist/agent-src/commands/feature/roadmap.md +28 -1
  14. package/dist/agent-src/commands/implement-ticket.md +27 -0
  15. package/dist/agent-src/commands/jira-ticket.md +27 -0
  16. package/dist/agent-src/commands/pr/create.md +29 -0
  17. package/dist/agent-src/commands/pr/merge.md +60 -9
  18. package/dist/agent-src/commands/roadmap/ai-council.md +7 -1
  19. package/dist/agent-src/commands/roadmap/create.md +74 -27
  20. package/dist/agent-src/commands/roadmap/materialize.md +27 -0
  21. package/dist/agent-src/commands/roadmap/process-full.md +123 -18
  22. package/dist/agent-src/commands/team.md +22 -0
  23. package/dist/agent-src/contexts/authority/scope-growth-ownership.md +80 -0
  24. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +47 -0
  25. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +44 -3
  26. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +15 -15
  27. package/dist/agent-src/contexts/execution/decision-closure-execution.md +93 -0
  28. package/dist/agent-src/contexts/execution/fix-loop-ladder.md +108 -0
  29. package/dist/agent-src/contexts/execution/plan-confidence-gate.md +4 -2
  30. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +75 -6
  31. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
  32. package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
  33. package/dist/agent-src/guidelines/design-fidelity-routing.md +29 -0
  34. package/dist/agent-src/rules/autonomous-execution.md +15 -8
  35. package/dist/agent-src/rules/delegation-policy.md +23 -45
  36. package/dist/agent-src/rules/design-fidelity.md +32 -37
  37. package/dist/agent-src/rules/evaluator-independence.md +43 -49
  38. package/dist/agent-src/rules/test-first.md +41 -0
  39. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
  40. package/dist/agent-src/skills/ai-council/SKILL.md +11 -3
  41. package/dist/agent-src/skills/api-design/data/manifest.json +3 -3
  42. package/dist/agent-src/skills/database/data/manifest.json +4 -4
  43. package/dist/agent-src/skills/database/data/query-tuning.csv +3 -3
  44. package/dist/agent-src/skills/design-review/SKILL.md +50 -0
  45. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -4
  46. package/dist/agent-src/skills/experiment-loop/SKILL.md +31 -1
  47. package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
  48. package/dist/agent-src/skills/storybook-workshop/SKILL.md +42 -3
  49. package/dist/agent-src/skills/threat-modeling/SKILL.md +9 -4
  50. package/dist/agent-src/skills/threat-modeling/data/manifest.json +4 -4
  51. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +37 -3
  52. package/dist/agent-src/templates/agent-settings.md +1 -1
  53. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  54. package/dist/agent-src/templates/roadmaps.md +188 -0
  55. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
  56. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
  57. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
  58. package/dist/cli-delegate/check_update_banner.js +40 -2
  59. package/dist/cli-delegate/chunk-4E2W63DA.js +335 -0
  60. package/dist/cli-delegate/chunk-5R7HOLAF.js +99 -0
  61. package/dist/cli-delegate/{chunk-IVBPRCQO.js → chunk-6KFEC3G7.js} +1 -1
  62. package/dist/cli-delegate/{chunk-2TAQ2K4V.js → chunk-6KM6ORRY.js} +55 -386
  63. package/dist/cli-delegate/{chunk-2XY7ILBT.js → chunk-FC75PGJE.js} +42 -2
  64. package/dist/cli-delegate/{chunk-GYC3VRYN.js → chunk-FXYUYU4N.js} +57 -13
  65. package/dist/cli-delegate/{chunk-55ACLDUE.js → chunk-GJCBB2UG.js} +168 -10
  66. package/dist/cli-delegate/{chunk-AK6HODNQ.js → chunk-HDVVGPQW.js} +873 -539
  67. package/dist/cli-delegate/{chunk-H32DGUJH.js → chunk-P6ZHP5W2.js} +1 -1
  68. package/dist/cli-delegate/{chunk-57PN4GYJ.js → chunk-RGNIWTEA.js} +1 -1
  69. package/dist/cli-delegate/chunk-ROYYTEZU.js +39 -0
  70. package/dist/cli-delegate/{chunk-3FKR64R5.js → chunk-UNCRJBT3.js} +31 -7
  71. package/dist/cli-delegate/{chunk-2DK2VJWG.js → chunk-WGXTVKCQ.js} +20 -6
  72. package/dist/cli-delegate/chunk-YDPILCOL.js +152 -0
  73. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  74. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  75. package/dist/cli-delegate/cmd_conformance.js +90 -56
  76. package/dist/cli-delegate/cmd_doctor.js +7 -5
  77. package/dist/cli-delegate/cmd_explain.js +2 -2
  78. package/dist/cli-delegate/cmd_export.js +9 -7
  79. package/dist/cli-delegate/cmd_fleet.js +4 -2
  80. package/dist/cli-delegate/cmd_handoff.js +4 -4
  81. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  82. package/dist/cli-delegate/cmd_migrate.js +2 -2
  83. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  84. package/dist/cli-delegate/cmd_preflight.js +4 -2
  85. package/dist/cli-delegate/cmd_prune.js +10 -8
  86. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  87. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  88. package/dist/cli-delegate/cmd_session_recycle.js +2 -2
  89. package/dist/cli-delegate/cmd_settings_get.js +28 -2
  90. package/dist/cli-delegate/cmd_settings_migrate.js +9 -7
  91. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  92. package/dist/cli-delegate/cmd_sync.js +10 -8
  93. package/dist/cli-delegate/cmd_uninstall.js +16 -13
  94. package/dist/cli-delegate/cmd_update.js +1 -1
  95. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  96. package/dist/cli-delegate/cmd_validate.js +12 -10
  97. package/dist/cli-delegate/cmd_versions.js +1 -1
  98. package/dist/discovery/deprecation-report.md +1 -1
  99. package/dist/discovery/discovery-manifest.json +85 -38
  100. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  101. package/dist/discovery/discovery-manifest.summary.md +4 -4
  102. package/dist/discovery/dormancy-report.md +1 -1
  103. package/dist/discovery/orphan-report.md +1 -1
  104. package/dist/discovery/packs.json +10 -8
  105. package/dist/discovery/trust-report.md +3 -3
  106. package/dist/discovery/workspaces.json +8 -6
  107. package/dist/hooks/dispatch.js +1832 -1007
  108. package/dist/install/claudeRuleRewrite.js +14 -3
  109. package/dist/install/conflict.js +60 -10
  110. package/dist/install/conflictTracker.js +218 -0
  111. package/dist/install/fsPrimitives.js +54 -0
  112. package/dist/install/install.mjs +2007 -1481
  113. package/dist/install/manifestFiles.js +259 -0
  114. package/dist/install/preflight.js +14 -2
  115. package/dist/install/preserve.js +157 -0
  116. package/dist/install/recordedOwnership.js +132 -0
  117. package/dist/install/txlog.js +11 -2
  118. package/dist/mcp/registry-manifest.json +3 -3
  119. package/dist/mcp/server.json +2 -2
  120. package/dist/mcp/server.mjs +398 -39
  121. package/dist/router.json +1 -1
  122. package/dist/scripts/_lib/agent_settings.js +3 -2
  123. package/dist/scripts/_lib/fs_atomic.js +167 -0
  124. package/dist/scripts/_lib/installed_tools.js +460 -0
  125. package/dist/scripts/_lib/lean_projection_mode.js +3 -2
  126. package/dist/scripts/_lib/settings_renamed_keys.js +78 -0
  127. package/dist/server/routes/install.js +8 -0
  128. package/dist/server/routes/wizard.js +9 -3
  129. package/dist/server/schemas/settings.js +17 -5
  130. package/dist/shared/missionExecution.js +97 -0
  131. package/dist/ui/assets/{index-D0jaCRPM.js → index-DH1xc62v.js} +17 -17
  132. package/dist/ui/index.html +1 -1
  133. package/docs/MIGRATION.md +103 -0
  134. package/docs/contracts/settings-classes.md +26 -7
  135. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
  136. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
  137. package/docs/guidelines/design-fidelity-routing.md +29 -0
  138. package/package.json +1 -1
  139. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
  140. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
  141. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
  142. package/src/config/agent-settings.template.yml +139 -27
  143. package/src/config/auto-rule-budget.json +16 -0
  144. package/src/config/ci-local-parity.yml +18 -5
  145. package/src/config/continuity-surface.json +21 -0
  146. package/src/config/gate-coverage.yml +146 -13
  147. package/src/config/gate-violation-baselines.json +6 -6
  148. package/src/config/hook-token-budget.json +2 -0
  149. package/src/config/loop-surfaces.yaml +215 -0
  150. package/src/config/platform-anchor.json +3 -2
  151. package/src/config/release-gate-locality.yml +11 -0
  152. package/src/config/routing-coverage-seed.json +18 -4
  153. package/src/config/rule-enforcement-baseline.json +0 -1
  154. package/src/install/claudeRuleRewrite.ts +16 -2
  155. package/src/install/conflict.ts +65 -9
  156. package/src/install/conflictTracker.ts +299 -0
  157. package/src/install/fsPrimitives.ts +54 -0
  158. package/src/install/manifestFiles.ts +312 -0
  159. package/src/install/preflight.ts +16 -2
  160. package/src/install/preserve.ts +205 -0
  161. package/src/install/recordedOwnership.ts +149 -0
  162. package/src/install/txlog.ts +11 -2
  163. package/src/install/types.ts +19 -4
  164. package/src/scripts/_cli/cmd_conformance.ts +88 -15
  165. package/src/scripts/_cli/cmd_doctor.ts +4 -3
  166. package/src/scripts/_cli/cmd_route_explain.ts +9 -2
  167. package/src/scripts/_cli/cmd_settings_get.ts +44 -0
  168. package/src/scripts/_cli/doctor_execution.ts +90 -0
  169. package/src/scripts/_lib/activation_payload.ts +247 -0
  170. package/src/scripts/_lib/agent_settings.ts +4 -2
  171. package/src/scripts/_lib/authority_path.ts +102 -0
  172. package/src/scripts/_lib/cascade_base.ts +94 -0
  173. package/src/scripts/_lib/changelog_eras.ts +7 -2
  174. package/src/scripts/_lib/continuation_ladder.ts +149 -2
  175. package/src/scripts/_lib/council_transport.ts +129 -0
  176. package/src/scripts/_lib/delivery_ready.ts +112 -0
  177. package/src/scripts/_lib/forge_protection.ts +267 -0
  178. package/src/scripts/_lib/hook_platform_keys.ts +27 -0
  179. package/src/scripts/_lib/json_python_parity.ts +127 -0
  180. package/src/scripts/_lib/lean_projection_mode.ts +14 -3
  181. package/src/scripts/_lib/loop_surfaces.ts +382 -0
  182. package/src/scripts/_lib/mission_record.ts +190 -0
  183. package/src/scripts/_lib/obligation_frequency.ts +217 -0
  184. package/src/scripts/_lib/obligations.ts +402 -0
  185. package/src/scripts/_lib/orchestration_record.ts +11 -20
  186. package/src/scripts/_lib/release_highlights.ts +199 -10
  187. package/src/scripts/_lib/release_holds.ts +493 -0
  188. package/src/scripts/_lib/release_migration_gate.ts +184 -0
  189. package/src/scripts/_lib/rides_along.ts +102 -0
  190. package/src/scripts/_lib/settings_renamed_keys.ts +82 -0
  191. package/src/scripts/_lib/test_delta.ts +166 -0
  192. package/src/scripts/_lib/test_provenance.ts +171 -0
  193. package/src/scripts/_lib/typed_op_grant.ts +246 -0
  194. package/src/scripts/_lib/typed_op_watch.ts +185 -0
  195. package/src/scripts/ai_council/config.ts +8 -11
  196. package/src/scripts/ai_council/fallback_config.ts +5 -3
  197. package/src/scripts/ai_council/ownership_classes.ts +118 -0
  198. package/src/scripts/ask_block_census.ts +285 -15
  199. package/src/scripts/check_enforcement_matrix.ts +624 -0
  200. package/src/scripts/check_gate_reachability.ts +173 -10
  201. package/src/scripts/check_generator_sync.ts +954 -0
  202. package/src/scripts/check_preamble_payload_budget.ts +75 -2
  203. package/src/scripts/check_release_highlights.ts +33 -1
  204. package/src/scripts/check_release_holds.ts +567 -0
  205. package/src/scripts/check_rule_projection_integrity.ts +22 -12
  206. package/src/scripts/check_test_delta.ts +294 -0
  207. package/src/scripts/check_test_weakening.ts +299 -0
  208. package/src/scripts/closure_scan.ts +333 -0
  209. package/src/scripts/compile_hook_manifest.ts +43 -3
  210. package/src/scripts/council_record_shape.ts +209 -0
  211. package/src/scripts/hook_manifest.json +1 -1
  212. package/src/scripts/hook_manifest.yaml +88 -9
  213. package/src/scripts/hooks/concern_registry.ts +4 -0
  214. package/src/scripts/hooks/design_pass_hook.ts +128 -3
  215. package/src/scripts/hooks/evidence_independence.ts +96 -0
  216. package/src/scripts/hooks/memory_recall_hook.ts +540 -0
  217. package/src/scripts/hooks/obligation_settle_hook.ts +182 -0
  218. package/src/scripts/hooks/rule_inject_hook.ts +49 -1
  219. package/src/scripts/hooks/run_continuation_hook.ts +17 -20
  220. package/src/scripts/hooks_doctor.ts +85 -0
  221. package/src/scripts/hooks_status.ts +19 -0
  222. package/src/scripts/install.ts +106 -206
  223. package/src/scripts/janitor.ts +7 -0
  224. package/src/scripts/lint_decision_classes.ts +464 -0
  225. package/src/scripts/lint_hook_manifest.ts +11 -0
  226. package/src/scripts/lint_major_migration_sections.ts +450 -0
  227. package/src/scripts/lint_plan_risk_register.ts +47 -3
  228. package/src/scripts/lint_roadmap_blockers.ts +61 -0
  229. package/src/scripts/lint_roadmap_producers.ts +202 -0
  230. package/src/scripts/measure_rule_budget.ts +101 -5
  231. package/src/scripts/new_roadmap.ts +37 -0
  232. package/src/scripts/orchestration_record.ts +0 -5
  233. package/src/scripts/release.ts +14 -98
  234. package/src/scripts/release_drill.ts +267 -1
  235. package/src/scripts/release_publication.ts +51 -0
  236. package/src/scripts/report_enforcement_drift.ts +566 -0
  237. package/src/scripts/report_host_injection_effect.ts +3 -11
  238. package/src/scripts/report_standing_payload_by_host.ts +26 -152
  239. package/src/scripts/schemas/agent-settings.schema.json +23 -0
  240. package/src/scripts/schemas/command.schema.json +4 -0
  241. package/src/scripts/scope_growth.ts +219 -0
  242. package/src/scripts/trigger_eval_grandfather.json +0 -1
  243. package/src/scripts/ui_conformance_probe.ts +622 -0
  244. package/src/server/schemas/settings.ts +31 -7
  245. package/src/shared/missionExecution.ts +126 -0
  246. package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
@@ -27,7 +27,7 @@
27
27
  document.documentElement.setAttribute('data-theme', theme);
28
28
  })();
29
29
  </script>
30
- <script type="module" crossorigin src="/assets/index-D0jaCRPM.js"></script>
30
+ <script type="module" crossorigin src="/assets/index-DH1xc62v.js"></script>
31
31
  <link rel="stylesheet" crossorigin href="/assets/index-jSfMW8_t.css">
32
32
  </head>
33
33
  <body>
package/docs/MIGRATION.md CHANGED
@@ -42,6 +42,109 @@ reason, which no arithmetic can.
42
42
  or that promises a future breaking removal, gets a row here in the same commit
43
43
  that makes the promise. A promise with no row is not tracked and will be missed.
44
44
 
45
+ ## 16.0.0 — the stored standing-payload ceiling is deleted
46
+
47
+ 💡 advisory · 🔄 automatic — **no consumer action.**
48
+
49
+ 16.0.0 carries one BREAKING entry: `feat(payload)!: delete the stored
50
+ standing-payload ceiling` ([`0b20000`](https://github.com/event4u-app/agent-config/commit/0b20000d48801fe4e0661660da610e1372642f7d)).
51
+
52
+ ### What went
53
+
54
+ Three keys left `ci_delivery` in
55
+ [`src/config/preamble-payload-budget.json`](../src/config/preamble-payload-budget.json):
56
+ `grace_ceiling`, `grace_measured_at`, and the raise-history key. `stored_ceiling`
57
+ left the bound set, the ceiling formula, the `boundBy` union and the `Budget`
58
+ type.
59
+
60
+ ### What replaces it
61
+
62
+ The bound is **computed per run** instead of stored:
63
+
64
+ ```
65
+ ceiling = max(design_ceiling, min(base, watermark) + active grant)
66
+ ```
67
+
68
+ `base` is the standing payload measured **at the base ref** of the pull request;
69
+ `watermark` pins that anchor for as long as an exception grant is live, so an
70
+ exceptional measurement never becomes the next base. The mechanism and its six
71
+ contract rules are in
72
+ [`src/scripts/_lib/measured_payload_ceiling.ts`](../src/scripts/_lib/measured_payload_ceiling.ts);
73
+ the decisions are ADR-275 (the formula) and ADR-276 (this deletion).
74
+
75
+ ### Who this asks something of — and it is not a consumer
76
+
77
+ **If you install `@event4u/agent-config`, there is nothing to migrate.** The
78
+ deleted keys are repository-governance configuration for this package's own CI;
79
+ no consumer holds a stored standing-payload ceiling, and no installed surface,
80
+ CLI verb, setting or projected artifact changed. The entry is BREAKING because
81
+ the config schema lost keys, not because a consumer contract did.
82
+
83
+ **If you contribute to this package**, two things follow. A ceiling can no
84
+ longer be widened by editing a field — there is no field — so a pull request
85
+ that grows the standing payload is refused unless it carries a recorded grant in
86
+ [`src/config/preamble-payload-exceptions.json`](../src/config/preamble-payload-exceptions.json).
87
+ And because the tree measures at its own design ceiling, the ordinary path is
88
+ **zero net growth per pull request**: payload added needs payload removed in the
89
+ same change.
90
+
91
+ ## 15.0.0 — two retired commands, and one retirement that did not happen
92
+
93
+ ✋ manual — **one thing to do, and one thing explicitly not to do.**
94
+
95
+ 15.0.0 carries two BREAKING entries. Only the first asks anything.
96
+
97
+ ### ✋ `/chat-history` and `/chat-history import` are gone
98
+
99
+ [`8b5226a`](https://github.com/event4u-app/agent-config/commit/8b5226aff24d93f8a5fecfa7525b9419d58524af)
100
+ removed both command files:
101
+
102
+ - `src/domains/meta/chat-history/command.md` → projected `/chat-history`
103
+ - `src/domains/meta/chat-history/import/command.md` → projected
104
+ `/chat-history import`
105
+
106
+ Invoking either now does nothing — the command is not in the projection, so the
107
+ host has no file to route to. If a script, a runbook or your own AGENTS.md names
108
+ either verb, remove the reference; it will not fail loudly.
109
+
110
+ **What is NOT gone**, and this is the part worth reading before you replace
111
+ anything: the runtime writer is untouched. `src/scripts/chat_history.ts`, the
112
+ `chat-history` hook concern, the `chat-history:hook` / `chat-history:checkpoint`
113
+ verbs and all six host dispatchers still run, and the `.agent-chat-history`
114
+ runtime file is still written. What was retired is the affordance that *read*
115
+ it back into a session.
116
+
117
+ **What replaces it: a manual reconstruction, not a restore.** Use
118
+ [`/agent-handoff`](../src/domains/meta/agent-handoff/command.md), which claims recording
119
+ and manual reconstruction and nothing more. The council that authorized this
120
+ removal was explicit that the two are not the same capability — recording,
121
+ locating a record, interpreting it, injecting it into a new session and
122
+ restoring usable context are separate, and only the first is demonstrated. It is
123
+ recorded as an **authorized capability loss**, so plan for reading a record
124
+ yourself rather than for an automatic resume.
125
+
126
+ ### 💡 The announced kernel-deny retirement did not ship — nothing to migrate
127
+
128
+ The second BREAKING entry reads
129
+ `retire the kernel-rule tool-call deny and the 24h soak`
130
+ ([`288190b`](https://github.com/event4u-app/agent-config/commit/288190b1a5a09a964cf4cc29fa356791bbfb8069)).
131
+ **It was reverted inside the same release** by
132
+ [`03e4eb7d`](https://github.com/event4u-app/agent-config/commit/03e4eb7de6b8c637cf41bbe60acb489b3a6658af),
133
+ after a two-round independent ratification review refused the replacement 2/2.
134
+
135
+ So 15.0.0 shipped with both intact: `block_kernel_rule_writes.ts` is registered
136
+ `fail_closed: true` on `pre_tool_use`, and the 24-hour soak in
137
+ `contexts/authority/kernel-rule-edits.md` is unchanged. The CI gate that was
138
+ proposed as a replacement, `check_kernel_edit_ratified`, landed **alongside**
139
+ the deny — that context file calls it "an ADDITION to this soak, never a
140
+ replacement".
141
+
142
+ **There is nothing to do.** No behavior was removed, so no migration exists for
143
+ it. If you already acted on the published line — dropped the hook binding from a
144
+ local override, or relaxed a kernel-edit workflow on the strength of it — put it
145
+ back. The correction is recorded at the head itself, in
146
+ [`archive/CHANGELOG-pre-16.0.0.md`](archive/CHANGELOG-pre-16.0.0.md) § 15.0.0.
147
+
45
148
  ## 14.22.x — the code-graph engine gets readers, and the MCP install hint changes
46
149
 
47
150
  💡 advisory · 🔄 automatic — **one exception, below.**
@@ -247,8 +247,21 @@ dispatch runs, not WHETHER the layer exists, so they keep their own C rows.
247
247
  |---|---|
248
248
  | A — preference | 26 |
249
249
  | B — consent | 3 |
250
- | C — guarded | 116 |
251
- | **Total** | **145** |
250
+ | C — guarded | 122 |
251
+ | **Total** | **151** |
252
+
253
+ It rose again on 2026-09-13 when `road-to-adversarial-verification-and-long-runs`
254
+ Phase 0 added three C keys: `quality.local_auto_run_in_mission` (`consent` — it
255
+ decides whether local verification runs at all inside a mission, which is the
256
+ same decision `quality.local_auto_run` carries for chat) and the two
257
+ `execution:` leaves, `fix_loop_max` and `escalation` (both `policy` — they bound
258
+ and route an autonomous run's own recovery, and an agent that could widen its own
259
+ bound has no bound). None is `derivable`: each states something no other surface
260
+ computes, so the anti-regrowth ratchet on that disposition is untouched. Two
261
+ branches added keys on the same day, so the totals in both tables are re-derived
262
+ from the class table on the MERGED tree rather than by adding either side's
263
+ delta — which is the arithmetic `lint_settings_classes` checks, and picking a
264
+ side is how a stated count comes to describe a tree that no longer exists.
252
265
 
253
266
  It rose to 142 on 2026-09-08 from two independent additions that landed in the same
254
267
  day and are counted together here: `lean_projection.hosts` (one C, `policy`, from
@@ -369,9 +382,9 @@ the template, which is the drift this contract exists to prevent.
369
382
  |---|---|
370
383
  | derivable | 83 |
371
384
  | un-inferrable | 9 |
372
- | consent | 44 |
373
- | policy | 9 |
374
- | **Total** | **145** |
385
+ | consent | 47 |
386
+ | policy | 12 |
387
+ | **Total** | **151** |
375
388
 
376
389
  First measured 2026-08-12 at 140 leaves (derivable 88 · consent 38 ·
377
390
  un-inferrable 9 · policy 5), from the table below rather than predicted — the
@@ -474,7 +487,7 @@ Rows follow template order, so a diff against the template reads straight down.
474
487
  | `projection.rule_packs` | C | `[]` | second allowlist axis on rule projection | derivable — the `auto` derivation already implemented in `src/install/rule_scope.ts` |
475
488
  | `discipline_profile` | C | `__DISCIPLINE_PROFILE__` | master switch for the discipline rule tier | derivable — its own `auto` resolution against `src/config/host-capabilities.yml` |
476
489
  | `rule_loading_tier` | C | `__RULE_LOADING_TIER__` | legacy master switch for rule loading | derivable — `discipline_profile` supersedes it with a documented mapping (minimal→off, balanced→essential, full→full) |
477
- | `lean_projection.mode` | C | `eager-all` | `thin` removes rule bodies from the agent's context | derivable — `probe_host_compliance.ts` already computes the per-host thin/eager recommendation |
490
+ | `lean_projection.mode` | C | `delivery` | `thin` and `delivery` remove rule bodies from the agent's standing context. Two defaults, and this column carries the template one: the shipped template has said `delivery` since ADR-267, while the parser fallback for a value that resolves from no layer stays `eager-all` (ADR-267 decision 4) | derivable — `probe_host_compliance.ts` already computes the per-host thin/eager recommendation |
478
491
  | `lean_projection.hosts` | C | `[claude-code]` | decides WHICH hosts a thinning mode may thin, so an added id removes rule bodies from that host's context | policy — the value is a package-level decision the tree already holds: ADR-267 scopes the shipped `delivery` flip to `claude-code` alone. NOT `derivable`, and the distinction is the whole reason for this row: the mechanism that would compute an admissible host set, `admissibleUnderE3` in `src/scripts/_lib/injection_effect.ts`, admits **nothing** today — `src/config/host-injection-effect.json` carries 1 `observed-false` and 8 `unobserved` rows and no `observed-true` — so a derivation would yield `[]` rather than the shipped `[claude-code]`. Naming a mechanism that returns empty as the replacement would put a key in the deletion queue whose deletion would silently change the default. Move target: the ADR plus that census, once a host earns an `observed-true` row |
479
492
  | `telegraph.speak` | C | `false` | ships a rule body; a token-cost lever in both directions | derivable — the telegraph kill-criterion bench verdict is a package-level decision, not a per-install one |
480
493
  | `tokens.rich_skills` | C | `"on"` | token-spend lever | derivable — the skill's own `token_budget_class: rich` declaration plus the CI ceiling in `lint_token_budget_discipline.ts` |
@@ -506,6 +519,9 @@ Rows follow template order, so a diff against the template reads straight down.
506
519
  | `project.improvement_pr_branch_prefix` | A | `improve/agent-` | branch-name cosmetics | derivable — the repo's own branch-naming convention, observable from `git branch -r` |
507
520
  | `project.audience` | C | `public` | C-test 4 — it governs the agent's own reasoning discipline: `self` makes the § 8-pre demand gate inert. Who a project is built for is a fact only its maintainer knows, so the agent never infers it and never asks; hand-edit or the GUI write route. The default is today's behaviour, so an install that never sets it is unchanged | policy |
508
521
  | `github.pr_reply_method` | A | `create_review_comment` | picks between two endpoints of one operation | derivable — the `auto` value already in the enum: the routing detects the working endpoint on first use and writes it back |
522
+ | `delivery.merge` | C | `off` | C-test 1 — it is the configuration half of merge authority, resolved by ADR-268 section 3. An agent that could write it could grant itself the capability the key gates, which is the exact shape the C fence exists to refuse. `off` is today's behavior, so an install that never sets it is unchanged | consent |
523
+ | `delivery.wait_for_ci` | C | `true` | C-test 1 — it authorises the run to keep spending time and tokens driving CI to a verdict rather than ending at push. A standing authorisation over the agent's own consumption is not a preference | consent |
524
+ | `delivery.pr_topology` | C | `single` | C-test 4 — `stacked` is a plan the owner makes, never one the agent picks, and the roadmap surface that consumes it is written before execution. An agent-writable value here would let a run choose its own delivery shape mid-mission | policy |
509
525
  | `augment.rules_use_symlinks` | A | `false` | reversible install mechanics | derivable — dev-mode detection at install time plus a symlink-capability probe on the target filesystem |
510
526
  | `eloquent.access_style` | A | `getters_setters` | code convention | derivable — the convention the project's existing models already use; `standards-from-config` reads it off the tree |
511
527
  | `chat_history.enabled` | C | `true` | kill-switch over a path that writes conversation content to disk | consent |
@@ -532,10 +548,13 @@ Rows follow template order, so a diff against the template reads straight down.
532
548
  | `roadmap.horizon_weeks` | C | `0` | a non-zero value relaxes a lint's plate-token ban | policy |
533
549
  | `roadmap.gate_budget.max_cost_per_run_usd` | C | `5` | per-run spend ceiling on class-1 gate execution | consent |
534
550
  | `roadmap.gate_budget.max_cost_per_rolling_7d_usd` | C | `25` | rolling spend ceiling on class-1 gate execution | consent |
535
- | `planning.challenge_on_create` | C | `true` | disables the plan-confidence gate | derivable — the gate's own confidence conditions; a confident plan passes straight through |
551
+ | `planning.closure_pass` | C | `true` | disables the plan-closure pass | derivable — the gate's own confidence conditions; a confident plan passes straight through |
536
552
  | `planning.risk_review` | C | `true` | disables the risk-register validator | derivable — `lint_plan_risk_register`'s own scope predicate (ready, non-draft plans only) |
537
553
  | `planning.completion_review` | C | `true` | disables the completion-review validator | derivable — `check_completion_review`'s own scope predicate, bound to the current diff hash |
538
554
  | `quality.local_auto_run` | C | `false` | governs whether local verification runs at all | consent |
555
+ | `quality.local_auto_run_in_mission` | C | `true` | governs whether local verification runs at all inside an autonomous mission | consent |
556
+ | `execution.fix_loop_max` | C | `10` | bounds how long an autonomous run may keep attempting one failing target | policy |
557
+ | `execution.escalation` | C | `['independent', 'council', 'team', 'owner_owned_check']` | names the rungs an autonomous run walks before any owner ask | policy |
539
558
  | `design.fidelity_mode` | C | `strict` | strict-mode selector, one of whose values is a Hard Floor | policy |
540
559
  | `design.approximation.enabled` | C | `false` | lets a value change without a per-value confirmation; enabling it is a consumer-facing default flip | consent |
541
560
  | `design.approximation.tolerance.color` | C | `null` | decides which colour deviations may be taken silently | policy |
@@ -93,6 +93,63 @@ Update stale idioms to the version the project **actually runs** — but only wh
93
93
  - Subordinate to `no-cheap-questions` (self-check items 3 & 14 — real trade-off, not a disguised continuation/commit ask), `autonomous-execution` (the end-of-session batch must not read as "shall I continue?"), `user-interaction`, `ask-when-uncertain` (one batched prompt = one question).
94
94
  - Threshold to surface at all: a **real, nameable** improvement with a concrete benefit. Cosmetic nitpicks with no trade-off → drop silently. The live-security carve-out is the only case that interrupts or overrides autonomy.
95
95
 
96
+ ## The other axis — who owns the growth
97
+
98
+ The ladder above sizes a change: *is this small and aligned enough to do now.*
99
+ It does not say **whose decision it is**, and both must clear before work
100
+ happens inline — something small and council-owned is still not the agent's to
101
+ decide, and something agent-owned and large is still bounded by
102
+ `minimal-safe-diff`.
103
+
104
+ Three closed lists answer the ownership half: six agent-owned kinds (done
105
+ inline, recorded as a scope delta in the PR body, never asked about), four
106
+ council-owned (routed through the ownership ladder, reaching the owner in none
107
+ of them), and two owner-owned. Anything matching none of them is not scope
108
+ growth at all — it is a follow-up artifact, and the mission does not expand to
109
+ hold it.
110
+
111
+ Full enumeration: [`scope-growth-ownership`](../../../src/agent-src/contexts/authority/scope-growth-ownership.md).
112
+ One item classifies deterministically with
113
+ `./scripts-run src/scripts/scope_growth "<description>"`; `unknown` is a real
114
+ verdict there, never a fallback to the cheapest rung.
115
+
116
+ ## Inside a mission — the middle rung becomes an artifact
117
+
118
+ `road-to-adversarial-verification-and-long-runs` 6.1. The ladder's middle rung is
119
+ **note + ask**, and inside an autonomous mission there is nobody to ask. Left
120
+ unreplaced the rung collapses in one of two bad directions, and both are failures
121
+ this suite already names: every spotted issue becomes a fix (the scope creep
122
+ [`minimal-safe-diff`](minimal-safe-diff-mechanics.md) exists to stop), or every
123
+ one becomes silence (the look-away `active-remediation` exists to stop).
124
+
125
+ So under a mission the middle rung is **emit a follow-up artifact and leave the
126
+ code alone**.
127
+
128
+ **What may ride along at all** — nine kinds, and the list is closed:
129
+ characterization tests · regression tests · a small adjacent bug · naming · types
130
+ · robustness · local dead code · simplifying code the mission already touched ·
131
+ testability.
132
+
133
+ **Six criteria, ALL of which must hold** for one of those to ride along: local to
134
+ the path the mission is already touching · small · low blast radius · clearly
135
+ correct · testable in the same commit · carries no new product decision.
136
+
137
+ ```
138
+ THE SIX ARE AND-ED, NEVER SCORED.
139
+ A SCORED VERSION LETS A LARGE CHANGE BUY ITS WAY IN WITH FIVE CHEAP YESES,
140
+ WHICH IS HOW A BOY-SCOUT RULE BECOMES A REFACTOR LICENCE.
141
+ ```
142
+
143
+ The **characterisation is the agent's judgement; the DECISION is mechanical** —
144
+ `_lib/rides_along.ts` takes the six booleans and returns the rung, so the same
145
+ inputs always land the same way and a later reader can check the call rather than
146
+ re-litigate the taste.
147
+
148
+ **A deferral states every reason it was deferred**, not the first one it hit. The
149
+ artifact exists because the issue is still owed, and "it failed one of six" is not
150
+ something a later triage can act on. A deferral with no reason is the
151
+ note-and-forget this rule already forbids, wearing an artifact's clothes.
152
+
96
153
  ## See also
97
154
 
98
155
  - [`active-remediation`](../../../src/rules/active-remediation.md) — the rule this file details (Iron Law + ladder + live-security carve-out).
@@ -86,6 +86,108 @@ point: this rule exists because a process that *looked* followed produced
86
86
  fabricated evidence, and claiming coverage it does not have would repeat that.
87
87
 
88
88
 
89
+ ## The audited failure, in full
90
+
91
+ Migrated out of the rule on 2026-09-13 under the same P4 pattern the rest of this
92
+ page follows: the rule keeps the obligation, this page carries the record. The
93
+ rule was re-sending all of it on every session and every spawn.
94
+
95
+ Measured, once, at maximum cost (conformance audit 2026-08-06):
96
+
97
+ > The agent dispatched a "blind reviewer" over its own change. It wrote that
98
+ > reviewer's prompt itself, put **"NO-FINDINGS is expected and welcome"** into it,
99
+ > and narrowed the scope to four files it chose. The reviewer returned
100
+ > NO-FINDINGS. That honest-null was committed as **binding gate evidence**. An
101
+ > unsteered pass over the same delta later found 5 findings, one of them
102
+ > critical, already live on the trunk.
103
+
104
+ The agent's own retro named it exactly, in the maintainer's own words:
105
+
106
+ *DE: "Die Fabrikation lag nicht im Weglassen des Reviews — sie lag in meinem Prompt. Ich habe die Antwort vorgeladen und dann als Evidenz verbucht." · EN: "The fabrication was not in skipping the review — it was in my prompt. I pre-loaded the answer and then booked it as evidence."*
107
+
108
+ The review ran. The process was followed. The evidence was manufactured anyway.
109
+
110
+ ## The softer form — why the phrase list cannot see it
111
+
112
+ The Iron Law forbids **authoring the verdict** into an evaluator's prompt. There
113
+ is a weaker move that evades it while doing the same work, and it is the one an
114
+ orchestrator reaches for without noticing: **stating an expectation**.
115
+
116
+ *"NO-FINDINGS is expected"* is a prediction, not a verdict — and it steered a real
117
+ review into an honest-null that five findings on the trunk later refuted. A prompt
118
+ that says what the author thinks the answer is has authored the answer, whatever
119
+ grammatical mood it used. The guard's pre-loaded-verdict detector is a PHRASE
120
+ list, so it catches recurrences of known steering wording and not steering as
121
+ such; this distinction is the gap it cannot close, which is why the obligation is
122
+ stated in the rule rather than delegated to the detector.
123
+
124
+ ## Tests are evaluators — levels, workflow, and the weakening ladder
125
+
126
+ `road-to-adversarial-verification-and-long-runs` Phase 2. The rule states the
127
+ obligation; this section carries the detail it points at.
128
+
129
+ ### The five levels
130
+
131
+ | Level | Author | What it actually buys |
132
+ |---|---|---|
133
+ | **L0** | the same agent, same session | nothing against self-confirmation. **Fallback only** — permitted when no other route exists, and then said out loud. |
134
+ | **L1** | another session, same model | a fresh context. **Not** a different judgement: with one provider configured this is the same model reviewing its own work, holding a label that says otherwise. |
135
+ | **L2** | another model | different training, different blind spots. The first level that buys a genuinely second opinion. |
136
+ | **L3** | another provider | independent training data, independent failure modes, independent incentives. |
137
+ | **L4** | a multi-provider council or team | L3 plus disagreement that is visible rather than averaged away. |
138
+
139
+ **Critical behavior — security, authority, data loss, merge control — targets
140
+ L3 or L4 wherever two providers are configured.** Wherever, not always: with one
141
+ provider the honest ceiling is L2, and the level is read from `agent-config
142
+ council:status`'s actual provider count rather than assumed from a config file
143
+ that may describe an intention.
144
+
145
+ ### The workflow
146
+
147
+ ```
148
+ acceptance behaviour → INDEPENDENT AUTHOR → RED evidence → implementer → GREEN
149
+ → INDEPENDENT VALIDATOR
150
+ ```
151
+
152
+ Five arrows, and the two capitalised roles are the ones that may not be the
153
+ implementer. **RED evidence** is not ceremony: a test never shown red has unknown
154
+ sensitivity, so a suite that was green from the first run has proven nothing
155
+ about the code and everything about the assertions being vacuous.
156
+
157
+ ### What an implementer may never do silently
158
+
159
+ Weaken an assertion · delete a failing test · skip or `xfail` it · loosen a
160
+ threshold · change fixture semantics to fit the code.
161
+
162
+ Each of these is a legitimate change *sometimes*, which is exactly why the
163
+ prohibition is on doing it **silently** rather than on doing it. Where the test
164
+ genuinely looks wrong, the ladder is: **evidence** (what the test asserts, what
165
+ the code does, why they disagree) → **independent test review** → **council or
166
+ team** → change only after an independent verdict.
167
+
168
+ **The owner is not the arbiter.** Routing this to the owner converts a technical
169
+ disagreement the tree can settle into an interrupt only the owner can clear, and
170
+ it is the same count-to-an-ask move the recovery ladder removes.
171
+
172
+ ### Test-quality validation — one question, before delivery
173
+
174
+ *Would these tests fail under plausible wrong implementations?* An independent
175
+ instance answers it, looking for: tautologies · algorithm duplication (the test
176
+ re-implements the thing it is testing, so both are wrong together) · snapshot
177
+ overuse · missing boundary and error cases · over-mocking (the mock, not the
178
+ code, is what passes) · expectations changed to fit the code · a test never shown
179
+ red.
180
+
181
+ The validator's **identity and provider go into the evidence**. An unattributed
182
+ validation is not one — it cannot be checked for the independence it claims, and
183
+ `evaluator-independence`'s own recorded failure is exactly a verdict nobody could
184
+ trace back to the prompt that produced it.
185
+
186
+ This is deliberately **not** mutation-testing infrastructure (K3 of that
187
+ roadmap). Mutation testing is the industrial form of the same question; one
188
+ independent instance asking it in prose is the cheap first form, and shipping the
189
+ cheap form now beats deferring the question until the infrastructure exists.
190
+
89
191
  ## See also
90
192
 
91
193
  - [`evaluator-independence`](../../../src/rules/evaluator-independence.md) — the rule this page carries the argument for.
@@ -13,6 +13,35 @@ Migrated out of `design-fidelity.md` on 2026-09-09 under the council verdict on
13
13
  the operative pointers the same verdict requires, not an arbitrary line cut. The
14
14
  rule keeps the obligations; this holds the reasoning behind them.
15
15
 
16
+ ### The matcher, and why each shipped class is shaped that way
17
+
18
+ Migrated out of `design-fidelity.md` on 2026-09-18 under
19
+ `road-to-design-fidelity-proof` Phase 1.1 — the rule keeps the operative class
20
+ list, this holds the argument behind each one.
21
+
22
+ Matching is plain lower-cased substring containment on the prompt, plus fnmatch
23
+ over the open files. Three handover classes must reach this rule: an English
24
+ phrasing, a German one, and a prompt carrying **no** keyword at all because the
25
+ artifact is simply attached. The last is covered by two file patterns:
26
+ `*design.html`, the conventional handover filename, and `*.dc.html`, the Claude
27
+ Design canvas artboard — which `*design.html` cannot match, because it compiles
28
+ to `^(?:.*design\.html)$` and `ToDo.dc.html` does not end in `design.html`.
29
+ Neither is `*.html`, which would fire on every HTML edit in every project and be
30
+ strictly worse than the gap it closes; `near-plain-html-open-file` pins that
31
+ form silent. A handover under some other filename needs one word in the prompt.
32
+
33
+ Two further handover shapes carry the artifact without any of the above:
34
+
35
+ - **A capability URL.** A published artifact is handed over as a link, not a
36
+ file — so `phrase: "claude.site/artifacts"` fires on the *published-artifact
37
+ path*, not on the host. `claude.ai` alone is a chat link and must stay quiet:
38
+ a keyword on the bare domain would fire on "I pasted this from claude.ai",
39
+ which is a conversation reference, not a spec.
40
+ - **A design-system directory.** `path_prefix: ".claude/design-system/"` — the
41
+ conventional location for a handed-over token/component set. The prefix is the
42
+ vendor-scoped directory, never a bare `design-system/`, which is a normal
43
+ source folder in a large fraction of frontend repos.
44
+
16
45
  ### The withdrawn builder-URL trigger
17
46
 
18
47
  A page built in Lovable / v0 / bolt and handed over as a share link is a
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
3
  "mcpName": "io.github.event4u-app/agent-config",
4
- "version": "16.0.0",
4
+ "version": "16.1.0",
5
5
  "description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) — every claim machine-checked, including the counts in these badges.",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -78,6 +78,41 @@ export const VOLATILE_KEYS: ReadonlyArray<string> = [
78
78
  /** Why the loop stopped, or that it has budget left. */
79
79
  export type SelfFixKind = 'retry' | 'exhausted' | 'no_progress';
80
80
 
81
+ /**
82
+ * `SelfFixKind` in the vocabulary a reader can aggregate across surfaces.
83
+ *
84
+ * `Outcome.PARTIAL` says the loop stopped without a green; it cannot say
85
+ * whether the budget ran out or the target stopped moving, and those want
86
+ * different responses — a bigger budget against the first, a different
87
+ * approach against the second. Until now the distinction left this module only
88
+ * inside a free-text `message`, so the continuation hook's stops were
89
+ * countable and this loop's were not.
90
+ *
91
+ * The two values are members of `RunTerminalState`, whose authoritative
92
+ * declaration is `src/scripts/_lib/outcome_vocabularies.ts:RUN_TERMINAL_STATES`
93
+ * and whose prose home is `contexts/execution/terminal-states.md`. They are
94
+ * written as literals rather than imported because this file is a TEMPLATE:
95
+ * it ships into consumer projects that have no `src/scripts/_lib` to import
96
+ * from, and reaching across that boundary would break every install. It is a
97
+ * two-member projection across a packaging boundary, not a second vocabulary —
98
+ * nothing here may add a member the registry does not have.
99
+ */
100
+ export const RUN_TERMINAL_BY_KIND: Readonly<Record<Exclude<SelfFixKind, 'retry'>, string>> = {
101
+ exhausted: 'exhausted',
102
+ no_progress: 'stagnated',
103
+ };
104
+
105
+ /**
106
+ * The run-terminal value for a decision, or `null` while the loop is still live.
107
+ *
108
+ * `retry` has no terminal by construction — the loop has not stopped — and the
109
+ * null is returned rather than defaulted so a caller cannot accidentally stamp
110
+ * a terminal value onto a run that is still going.
111
+ */
112
+ export function run_terminal_for(kind: SelfFixKind): string | null {
113
+ return kind === 'retry' ? null : RUN_TERMINAL_BY_KIND[kind];
114
+ }
115
+
81
116
  /** Verdict of {@link decide} — pure, so the caller owns every mutation. */
82
117
  export interface SelfFixDecision {
83
118
  kind: SelfFixKind;
@@ -147,6 +182,27 @@ export function record_attempt(state: DeliveryState, lane: string, signature: st
147
182
  state.self_fix = container;
148
183
  }
149
184
 
185
+ /**
186
+ * Stamp the lane's run-terminal value onto `state.self_fix`.
187
+ *
188
+ * Written into the state the module already owns and the dispatcher already
189
+ * persists, rather than onto `StepResult` — `StepResult` carries `outcome`,
190
+ * `questions` and `message` and is shared by every directive in the engine, so
191
+ * widening it for one loop's stop reason would be a change to all of them.
192
+ *
193
+ * A `retry` decision writes nothing: the loop has not stopped, and a terminal
194
+ * value recorded mid-loop would be read as one by anything aggregating the
195
+ * field.
196
+ */
197
+ export function record_run_terminal(state: DeliveryState, lane: string, decision: SelfFixDecision): void {
198
+ const run_terminal = run_terminal_for(decision.kind);
199
+ if (run_terminal === null) return;
200
+ const container = _pyTruthy(state.self_fix) ? (state.self_fix as Record<string, Any>) : {};
201
+ const lane_state = _lane_state(state, lane);
202
+ container[lane] = { ...lane_state, run_terminal };
203
+ state.self_fix = container;
204
+ }
205
+
150
206
  /** DoD entries the agent has not recorded as proven. Never inferred. */
151
207
  export function unmet_dod(state: DeliveryState): Array<Record<string, Any>> {
152
208
  const dod = (state.ticket ?? {})['dod'];
@@ -213,8 +269,11 @@ export function partial_exit(args: {
213
269
  decision: SelfFixDecision;
214
270
  unmet: Array<Record<string, Any>>;
215
271
  rerun_directive: string;
272
+ /** Written the run-terminal value onto, when the caller has the state in hand. */
273
+ state?: DeliveryState;
216
274
  }): StepResult {
217
- const { lane, ticket_id, verdict, decision, unmet, rerun_directive } = args;
275
+ const { lane, ticket_id, verdict, decision, unmet, rerun_directive, state } = args;
276
+ if (state !== undefined) record_run_terminal(state, lane, decision);
218
277
  const reason =
219
278
  decision.kind === 'no_progress'
220
279
  ? `two consecutive attempts produced an identical \`${lane}\` verdict, ` +
@@ -244,7 +303,8 @@ export function partial_exit(args: {
244
303
  ],
245
304
  message:
246
305
  `Ticket ${ticket_id} ${lane} verdict is \`${String(verdict)}\` after ` +
247
- `${decision.attempts} self-fix attempt(s) (${decision.kind}); exiting PARTIAL.`,
306
+ `${decision.attempts} self-fix attempt(s) (${decision.kind}); exiting PARTIAL ` +
307
+ `(run_terminal: ${String(run_terminal_for(decision.kind))}).`,
248
308
  });
249
309
  }
250
310
 
@@ -225,6 +225,7 @@ function _blocked_on_bad_verdict(state: DeliveryState, verdict: Any): StepResult
225
225
  decision,
226
226
  unmet: unmet_dod(state),
227
227
  rerun_directive: 'run-tests',
228
+ state,
228
229
  });
229
230
  }
230
231
 
@@ -201,6 +201,7 @@ function _blocked_on_bad_verdict(state: DeliveryState, verdict: Any): StepResult
201
201
  decision,
202
202
  unmet: unmet_dod(state),
203
203
  rerun_directive: 'review-changes',
204
+ state,
204
205
  });
205
206
  }
206
207