@event4u/agent-config 10.4.0 → 12.0.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 (303) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +73 -182
  3. package/dist/agent-src/commands/agent-handoff.md +0 -1
  4. package/dist/agent-src/commands/agent-status.md +0 -1
  5. package/dist/agent-src/commands/agents/audit.md +0 -1
  6. package/dist/agent-src/commands/agents/init.md +0 -1
  7. package/dist/agent-src/commands/agents/optimize.md +0 -1
  8. package/dist/agent-src/commands/agents/user/accept.md +0 -1
  9. package/dist/agent-src/commands/agents/user/delete.md +0 -1
  10. package/dist/agent-src/commands/agents/user/init.md +0 -1
  11. package/dist/agent-src/commands/agents/user/review.md +0 -1
  12. package/dist/agent-src/commands/agents/user/show.md +0 -1
  13. package/dist/agent-src/commands/agents/user/update.md +0 -1
  14. package/dist/agent-src/commands/agents/user.md +0 -1
  15. package/dist/agent-src/commands/agents.md +0 -1
  16. package/dist/agent-src/commands/analytics/prune.md +0 -1
  17. package/dist/agent-src/commands/analytics/show.md +0 -1
  18. package/dist/agent-src/commands/analytics.md +0 -1
  19. package/dist/agent-src/commands/analyze/conformance.md +0 -1
  20. package/dist/agent-src/commands/analyze/decision.md +0 -1
  21. package/dist/agent-src/commands/analyze/inbox.md +0 -1
  22. package/dist/agent-src/commands/analyze/incident.md +0 -1
  23. package/dist/agent-src/commands/analyze/near-miss.md +0 -1
  24. package/dist/agent-src/commands/analyze/postmortem.md +0 -1
  25. package/dist/agent-src/commands/analyze/premortem.md +0 -1
  26. package/dist/agent-src/commands/analyze/reference-repo.md +0 -1
  27. package/dist/agent-src/commands/analyze.md +0 -1
  28. package/dist/agent-src/commands/brand/identity.md +0 -1
  29. package/dist/agent-src/commands/brand/review.md +0 -1
  30. package/dist/agent-src/commands/brand/strategy.md +0 -1
  31. package/dist/agent-src/commands/brand/tokens.md +0 -1
  32. package/dist/agent-src/commands/brand/voice.md +0 -1
  33. package/dist/agent-src/commands/brand.md +0 -1
  34. package/dist/agent-src/commands/bug/fix.md +0 -1
  35. package/dist/agent-src/commands/bug/investigate.md +0 -1
  36. package/dist/agent-src/commands/bug.md +0 -1
  37. package/dist/agent-src/commands/challenge-me/vision.md +0 -1
  38. package/dist/agent-src/commands/challenge-me/with-docs.md +0 -1
  39. package/dist/agent-src/commands/challenge-me.md +0 -1
  40. package/dist/agent-src/commands/chat-history/import.md +0 -1
  41. package/dist/agent-src/commands/chat-history.md +0 -1
  42. package/dist/agent-src/commands/check-current-md.md +0 -1
  43. package/dist/agent-src/commands/commit/in-chunks.md +0 -1
  44. package/dist/agent-src/commands/commit.md +0 -1
  45. package/dist/agent-src/commands/condense.md +0 -1
  46. package/dist/agent-src/commands/context/create.md +0 -1
  47. package/dist/agent-src/commands/context/refactor.md +0 -1
  48. package/dist/agent-src/commands/context.md +0 -1
  49. package/dist/agent-src/commands/contribution-precheck.md +0 -1
  50. package/dist/agent-src/commands/cost/profile.md +0 -1
  51. package/dist/agent-src/commands/cost/report.md +0 -1
  52. package/dist/agent-src/commands/cost.md +0 -1
  53. package/dist/agent-src/commands/council/analysis.md +0 -1
  54. package/dist/agent-src/commands/council/debate.md +13 -5
  55. package/dist/agent-src/commands/council/default.md +26 -12
  56. package/dist/agent-src/commands/council/design.md +0 -1
  57. package/dist/agent-src/commands/council/optimize.md +0 -1
  58. package/dist/agent-src/commands/council/pr.md +0 -1
  59. package/dist/agent-src/commands/council.md +1 -2
  60. package/dist/agent-src/commands/design-system/capture.md +0 -1
  61. package/dist/agent-src/commands/design-system/generate.md +23 -2
  62. package/dist/agent-src/commands/design-system/import.md +0 -1
  63. package/dist/agent-src/commands/design-system.md +0 -1
  64. package/dist/agent-src/commands/estimate-ticket.md +0 -1
  65. package/dist/agent-src/commands/explain-run.md +0 -1
  66. package/dist/agent-src/commands/feature/dev.md +0 -1
  67. package/dist/agent-src/commands/feature/explore.md +0 -1
  68. package/dist/agent-src/commands/feature/plan.md +0 -1
  69. package/dist/agent-src/commands/feature/refactor.md +0 -1
  70. package/dist/agent-src/commands/feature/roadmap.md +0 -1
  71. package/dist/agent-src/commands/feature.md +0 -1
  72. package/dist/agent-src/commands/fix/ci.md +0 -1
  73. package/dist/agent-src/commands/fix/comments.md +0 -1
  74. package/dist/agent-src/commands/fix/portability.md +0 -1
  75. package/dist/agent-src/commands/fix/pr-comments-loop.md +0 -1
  76. package/dist/agent-src/commands/fix/pr-comments.md +0 -1
  77. package/dist/agent-src/commands/fix/quality.md +0 -1
  78. package/dist/agent-src/commands/fix/refs.md +0 -1
  79. package/dist/agent-src/commands/fix/route.md +0 -1
  80. package/dist/agent-src/commands/fix/seeder.md +0 -1
  81. package/dist/agent-src/commands/fix.md +0 -1
  82. package/dist/agent-src/commands/ghostwriter/delete.md +0 -1
  83. package/dist/agent-src/commands/ghostwriter/fetch.md +0 -1
  84. package/dist/agent-src/commands/ghostwriter/list.md +0 -1
  85. package/dist/agent-src/commands/ghostwriter/show.md +0 -1
  86. package/dist/agent-src/commands/ghostwriter/write.md +0 -1
  87. package/dist/agent-src/commands/ghostwriter.md +0 -1
  88. package/dist/agent-src/commands/grill-me.md +0 -1
  89. package/dist/agent-src/commands/humanize.md +0 -1
  90. package/dist/agent-src/commands/image/analyse.md +0 -1
  91. package/dist/agent-src/commands/image/create.md +0 -1
  92. package/dist/agent-src/commands/image/verify.md +0 -1
  93. package/dist/agent-src/commands/image.md +0 -1
  94. package/dist/agent-src/commands/implement-ticket.md +0 -1
  95. package/dist/agent-src/commands/jira-ticket.md +0 -1
  96. package/dist/agent-src/commands/judge/on-diff.md +0 -1
  97. package/dist/agent-src/commands/judge/solo.md +0 -1
  98. package/dist/agent-src/commands/judge/steps.md +0 -1
  99. package/dist/agent-src/commands/judge.md +0 -1
  100. package/dist/agent-src/commands/knowledge/cross-repo.md +0 -1
  101. package/dist/agent-src/commands/knowledge/forget.md +0 -1
  102. package/dist/agent-src/commands/knowledge/ingest.md +0 -1
  103. package/dist/agent-src/commands/knowledge/list.md +0 -1
  104. package/dist/agent-src/commands/knowledge.md +0 -1
  105. package/dist/agent-src/commands/memory/add.md +0 -1
  106. package/dist/agent-src/commands/memory/learn-low-impact.md +0 -1
  107. package/dist/agent-src/commands/memory/load.md +0 -1
  108. package/dist/agent-src/commands/memory/mine-session.md +0 -1
  109. package/dist/agent-src/commands/memory/promote.md +0 -1
  110. package/dist/agent-src/commands/memory/propose.md +0 -1
  111. package/dist/agent-src/commands/memory.md +0 -1
  112. package/dist/agent-src/commands/mission/upgrade.md +0 -1
  113. package/dist/agent-src/commands/mode.md +0 -1
  114. package/dist/agent-src/commands/module/create.md +0 -1
  115. package/dist/agent-src/commands/module/explore.md +0 -1
  116. package/dist/agent-src/commands/module.md +0 -1
  117. package/dist/agent-src/commands/optimize/agents-dir.md +0 -1
  118. package/dist/agent-src/commands/optimize/augmentignore.md +0 -1
  119. package/dist/agent-src/commands/optimize/deep.md +0 -1
  120. package/dist/agent-src/commands/optimize/project.md +0 -1
  121. package/dist/agent-src/commands/optimize/prompt.md +0 -1
  122. package/dist/agent-src/commands/optimize/rtk.md +0 -1
  123. package/dist/agent-src/commands/optimize/skills.md +0 -1
  124. package/dist/agent-src/commands/optimize.md +0 -1
  125. package/dist/agent-src/commands/orchestrate.md +0 -1
  126. package/dist/agent-src/commands/override/create.md +0 -1
  127. package/dist/agent-src/commands/override/manage.md +0 -1
  128. package/dist/agent-src/commands/override.md +0 -1
  129. package/dist/agent-src/commands/package/reset.md +0 -1
  130. package/dist/agent-src/commands/package/test.md +0 -1
  131. package/dist/agent-src/commands/package.md +0 -1
  132. package/dist/agent-src/commands/post-as/ghostwriter.md +0 -1
  133. package/dist/agent-src/commands/post-as/me.md +0 -1
  134. package/dist/agent-src/commands/post-as.md +0 -1
  135. package/dist/agent-src/commands/pr/create/description-only.md +0 -1
  136. package/dist/agent-src/commands/pr/create.md +67 -28
  137. package/dist/agent-src/commands/prediction-pool.md +0 -1
  138. package/dist/agent-src/commands/prepare-for-review.md +0 -1
  139. package/dist/agent-src/commands/profile/activate.md +0 -1
  140. package/dist/agent-src/commands/profile/deactivate.md +0 -1
  141. package/dist/agent-src/commands/profile/show.md +0 -1
  142. package/dist/agent-src/commands/profile.md +0 -1
  143. package/dist/agent-src/commands/project/analyze.md +0 -1
  144. package/dist/agent-src/commands/project/health.md +0 -1
  145. package/dist/agent-src/commands/project.md +0 -1
  146. package/dist/agent-src/commands/refine-ticket.md +0 -1
  147. package/dist/agent-src/commands/research/deep.md +0 -1
  148. package/dist/agent-src/commands/research/report.md +0 -1
  149. package/dist/agent-src/commands/research.md +0 -1
  150. package/dist/agent-src/commands/review/changes.md +0 -1
  151. package/dist/agent-src/commands/review/routing.md +0 -1
  152. package/dist/agent-src/commands/review.md +0 -1
  153. package/dist/agent-src/commands/roadmap/ai-council.md +0 -1
  154. package/dist/agent-src/commands/roadmap/create.md +0 -1
  155. package/dist/agent-src/commands/roadmap/materialize.md +0 -1
  156. package/dist/agent-src/commands/roadmap/next.md +0 -1
  157. package/dist/agent-src/commands/roadmap/process-full.md +0 -1
  158. package/dist/agent-src/commands/roadmap/process-phase.md +0 -1
  159. package/dist/agent-src/commands/roadmap/process-step.md +0 -1
  160. package/dist/agent-src/commands/roadmap.md +0 -1
  161. package/dist/agent-src/commands/rule-compliance-audit.md +0 -1
  162. package/dist/agent-src/commands/security-audit-config.md +0 -1
  163. package/dist/agent-src/commands/skill/preview.md +0 -1
  164. package/dist/agent-src/commands/skill.md +0 -1
  165. package/dist/agent-src/commands/skills/discover.md +0 -1
  166. package/dist/agent-src/commands/skills.md +0 -1
  167. package/dist/agent-src/commands/sync/agent-settings.md +0 -1
  168. package/dist/agent-src/commands/sync/gitignore/fix.md +0 -1
  169. package/dist/agent-src/commands/sync/gitignore.md +0 -1
  170. package/dist/agent-src/commands/sync.md +0 -1
  171. package/dist/agent-src/commands/tdd/green.md +0 -1
  172. package/dist/agent-src/commands/tdd/red.md +0 -1
  173. package/dist/agent-src/commands/tdd/refactor.md +0 -1
  174. package/dist/agent-src/commands/tdd.md +0 -1
  175. package/dist/agent-src/commands/team/adversarial.md +0 -1
  176. package/dist/agent-src/commands/team/delegate.md +0 -1
  177. package/dist/agent-src/commands/team/review.md +0 -1
  178. package/dist/agent-src/commands/team/status.md +0 -1
  179. package/dist/agent-src/commands/team-knowledge/bootstrap.md +0 -1
  180. package/dist/agent-src/commands/team-knowledge/consolidate.md +0 -1
  181. package/dist/agent-src/commands/team-knowledge.md +0 -1
  182. package/dist/agent-src/commands/team.md +0 -1
  183. package/dist/agent-src/commands/tests/create.md +0 -1
  184. package/dist/agent-src/commands/tests/e2e-heal.md +0 -1
  185. package/dist/agent-src/commands/tests/e2e-plan.md +0 -1
  186. package/dist/agent-src/commands/tests/execute.md +0 -1
  187. package/dist/agent-src/commands/tests.md +0 -1
  188. package/dist/agent-src/commands/threat-model.md +0 -1
  189. package/dist/agent-src/commands/update-form-request-messages.md +0 -1
  190. package/dist/agent-src/commands/upstream-contribute.md +0 -1
  191. package/dist/agent-src/commands/video/from-script.md +0 -1
  192. package/dist/agent-src/commands/video/from-song.md +0 -1
  193. package/dist/agent-src/commands/video/scene.md +0 -1
  194. package/dist/agent-src/commands/video/stitch.md +0 -1
  195. package/dist/agent-src/commands/video/storyboard.md +0 -1
  196. package/dist/agent-src/commands/video.md +0 -1
  197. package/dist/agent-src/commands/work.md +0 -1
  198. package/dist/agent-src/commands/worktree/cleanup.md +0 -1
  199. package/dist/agent-src/commands/worktree/create.md +5 -4
  200. package/dist/agent-src/commands/worktree/status.md +0 -1
  201. package/dist/agent-src/commands/worktree/verify.md +0 -1
  202. package/dist/agent-src/commands/worktree.md +0 -1
  203. package/dist/agent-src/rules/settings-ask-protocol.md +14 -9
  204. package/dist/agent-src/skills/ai-council/SKILL.md +24 -6
  205. package/dist/agent-src/skills/corpus-grounding/SKILL.md +12 -1
  206. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +215 -7
  207. package/dist/agent-src/skills/corpus-grounding/scripts/ground.ts +39 -1
  208. package/dist/agent-src/skills/design-intelligence/ATTRIBUTION.md +19 -2
  209. package/dist/agent-src/skills/design-intelligence/data/manifest.json +36 -1
  210. package/dist/agent-src/skills/design-intelligence/data/motion.csv +17 -0
  211. package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -0
  212. package/dist/agent-src/skills/git-workflow/SKILL.md +17 -3
  213. package/dist/agent-src/skills/pdf-tools/SKILL.md +1 -0
  214. package/dist/agent-src/skills/skill-writing/SKILL.md +35 -0
  215. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +9 -6
  216. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +25 -21
  217. package/dist/agent-src/templates/agent-settings.md +0 -1
  218. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  219. package/dist/cli/commands/commands.candidates.test.js +1 -1
  220. package/dist/cli/commands/commands.candidates.test.js.map +1 -1
  221. package/dist/cli/commands/commands.js +9 -15
  222. package/dist/cli/commands/commands.js.map +1 -1
  223. package/dist/cli/commands/profiles.test.js +7 -7
  224. package/dist/cli/commands/profiles.test.js.map +1 -1
  225. package/dist/cli/discovery/loadManifest.js.map +1 -1
  226. package/dist/cli/main.js +2 -2
  227. package/dist/cli/main.js.map +1 -1
  228. package/dist/cli-delegate/{chunk-BV3WR67D.js → chunk-55WZN5VF.js} +3 -6
  229. package/dist/cli-delegate/{chunk-X3VOARZD.js → chunk-L565YFXH.js} +3 -3
  230. package/dist/cli-delegate/{chunk-JMQZ7MM5.js → chunk-MNWRDMR5.js} +1 -1
  231. package/dist/cli-delegate/{chunk-IR3IVRVC.js → chunk-NLP54U3J.js} +2 -1
  232. package/dist/cli-delegate/{chunk-FV34EGEX.js → chunk-NN4KW4HZ.js} +1 -1
  233. package/dist/cli-delegate/{chunk-6ENSXSBW.js → chunk-PPQO4NGR.js} +1 -1
  234. package/dist/cli-delegate/{chunk-6LOPHJLD.js → chunk-RYNADUFG.js} +1 -1
  235. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  236. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  237. package/dist/cli-delegate/cmd_conformance.js +16 -4
  238. package/dist/cli-delegate/cmd_doctor.js +2 -2
  239. package/dist/cli-delegate/cmd_explain.js +2 -2
  240. package/dist/cli-delegate/cmd_export.js +4 -4
  241. package/dist/cli-delegate/cmd_handoff.js +2 -2
  242. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  243. package/dist/cli-delegate/cmd_migrate.js +2 -2
  244. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  245. package/dist/cli-delegate/cmd_prune.js +4 -4
  246. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  247. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  248. package/dist/cli-delegate/cmd_session_recycle.js +1 -1
  249. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  250. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  251. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  252. package/dist/cli-delegate/cmd_sync.js +4 -4
  253. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  254. package/dist/cli-delegate/cmd_update.js +1 -1
  255. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  256. package/dist/cli-delegate/cmd_validate.js +4 -4
  257. package/dist/cli-delegate/cmd_versions.js +1 -1
  258. package/dist/discovery/deprecation-report.md +1 -1
  259. package/dist/discovery/discovery-manifest.json +216 -415
  260. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  261. package/dist/discovery/discovery-manifest.summary.md +2 -2
  262. package/dist/discovery/dormancy-report.md +1 -1
  263. package/dist/discovery/orphan-report.md +1 -1
  264. package/dist/discovery/packs.json +3 -3
  265. package/dist/discovery/trust-report.md +1 -1
  266. package/dist/discovery/workspaces.json +3 -3
  267. package/dist/hooks/dispatch.js +68 -14
  268. package/dist/install/install.mjs +5 -7
  269. package/dist/mcp/registry-manifest.json +3 -3
  270. package/dist/mcp/server.json +2 -2
  271. package/dist/mcp/server.mjs +48 -6
  272. package/dist/scripts/_lib/agent_settings.js +8 -0
  273. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  274. package/dist/server/schemas/settings.js +3 -4
  275. package/dist/server/schemas/settings.js.map +1 -1
  276. package/dist/ui/assets/{index-5fXOHoVh.js → index-B0aMJnuz.js} +2 -2
  277. package/dist/ui/assets/{index-5fXOHoVh.js.map → index-B0aMJnuz.js.map} +1 -1
  278. package/dist/ui/index.html +1 -1
  279. package/docs/MIGRATION.md +1 -0
  280. package/docs/contracts/settings-classes.md +53 -9
  281. package/package.json +1 -1
  282. package/src/config/agent-settings.template.yml +49 -18
  283. package/src/config/gate-coverage.yml +13 -3
  284. package/src/config/gate-violation-baselines.json +4 -4
  285. package/src/config/pack-size-budget.json +3 -2
  286. package/src/scripts/_dispatch.bash +42 -5
  287. package/src/scripts/_lib/agent_settings.ts +8 -0
  288. package/src/scripts/audit_command_surface.ts +21 -15
  289. package/src/scripts/build_catalog_index.ts +1 -1
  290. package/src/scripts/build_discovery_manifest.ts +30 -34
  291. package/src/scripts/check_branch_freshness.ts +393 -12
  292. package/src/scripts/external_sources_denylist.json +7 -2
  293. package/src/scripts/gen_discovery_baseline.ts +3 -3
  294. package/src/scripts/hook_manifest.yaml +20 -0
  295. package/src/scripts/hooks/subagent_ledger_hook.ts +17 -4
  296. package/src/scripts/lint_command_tiers.ts +29 -75
  297. package/src/scripts/lint_originality.ts +101 -14
  298. package/src/scripts/schemas/command.schema.json +4 -9
  299. package/src/scripts/schemas/skill.schema.json +10 -1
  300. package/src/scripts/session_register_hook.ts +120 -10
  301. package/src/scripts/skill_linter.ts +82 -2
  302. package/src/scripts/worktree_cleanup_check.ts +111 -7
  303. package/src/server/schemas/settings.ts +3 -6
@@ -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-5fXOHoVh.js"></script>
30
+ <script type="module" crossorigin src="/assets/index-B0aMJnuz.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
@@ -16,6 +16,7 @@ releaser here on every `release:major`.
16
16
 
17
17
  | Surface | Committed | Deprecation notice due | Removal due | Reversal condition |
18
18
  |---|---|---|---|---|
19
+ | Free-text `compatibility` skill-frontmatter field (`src/scripts/schemas/skill.schema.json`) | 2026-08-14 | shipped 2026-08-14 — `deprecated: true` + superseded-by note in the schema; `harness_compat` lands beside it, additively | next major after the notice — **not pinned here** (removal date is maintainer-owned, same stance as the manifest `tier` entry, whose `sunset` shipped `null`) | The public Agent-Skills spec makes `compatibility` load-bearing for cross-host portability, or an external consumer is found reading it. `harness_compat` is package-local; `compatibility` mirrors the public spec, so keeping the mirror stays cheaply reversible. Superseded by `harness_compat` (class) + `runtime_requires` (probeable detail); both users (`docx-authoring`, `pdf-tools`) already carry both fields, so nothing breaks on removal day. |
19
20
  | `code_graph` native code-graph engine (`code_graph.enabled`, the `code-intelligence` skill's native arm, `code_graph_nudge_hook`) | 2026-07-28 | next major after 9.x | the major after that | A consumer case the graph answers and disciplined grep cannot. Measured null: recall 0.365 vs grep 0.797 (`docs/CLAIMS.md` `code-graph-retrieval-null`). Until then `enabled: false` is permanent. **Its parser pair (`web-tree-sitter@0.24.7` / `tree-sitter-wasms@0.1.13`, ~51 MB unpacked) moved from `dependencies` to `devDependencies` ahead of the schedule, so consumers no longer install it — the runtime paths (CLI leaf, nudge hook, skill, rule) stay registered until the removal date above, but re-enabling now also means installing that ABI-locked pair yourself.** |
20
21
 
21
22
  **Adding a row:** any change that ships a capability as default-off-pending-removal,
@@ -39,9 +39,10 @@ surface without a consumer.
39
39
  **It governs writes, not reads.** Every class is readable by everything. A C
40
40
  class does not hide a value; it refuses to let a non-human change it.
41
41
 
42
- **It governs writes, not asks.** Four settings ship an `ask` value in their own
43
- enum (`tokens.rich_skills`, `subagents.adversarial_council`, `worktrees.mode`,
44
- `decision_engine.on_block`).
42
+ **It governs writes, not asks.** Three settings ship an `ask` value in their own
43
+ enum (`tokens.rich_skills`, `subagents.adversarial_council`,
44
+ `decision_engine.on_block`). It was four until ADR-229 deleted
45
+ `worktrees.mode`.
45
46
  Those are C-class here, and that is not a contradiction: the class says who may
46
47
  *persist* a new value; the `ask` value says what happens *at runtime* when the
47
48
  setting is already set to `ask`. A C-class key set to `ask` still produces a
@@ -141,6 +142,47 @@ larger set; it is the set that passes both halves.
141
142
  | `personal.canary_name` | un-inferrable, and answering arms the session-degradation canary; one keypress to accept the prefill | `""` (canary dark) |
142
143
  | `memory.learn_on_session_end` | it turns on automatic memory writes at the end of every session — a standing write the user should authorise | `false` |
143
144
 
145
+ ## Class B is a persistence property, not an enforcement claim
146
+
147
+ Recorded 2026-08-13, from `road-to-zero-settings` step 3.2 — the step that asked
148
+ each class-B key *"does the action need authorising at all?"*. Two of the three
149
+ answers turned out not to be about the keys.
150
+
151
+ ```
152
+ CLASS B SAYS: MAY BE ASKED ONCE, THEN PERSISTED. IT SAYS NOTHING ABOUT
153
+ WHETHER ANYTHING CAN REFUSE THE ACTION. THE DISPOSITION SAYS THAT.
154
+ A `consent` KEY NEEDS A MECHANISM THAT CAN WITHHOLD, OR AN EXPLICIT
155
+ PROSE-ONLY LABEL. AN `un-inferrable` KEY NEEDS ONLY PERSISTENCE.
156
+ ```
157
+
158
+ The two axes are independent, and reading class B as implying an enforcement
159
+ obligation is what made two non-problems look like problems:
160
+
161
+ - **`personal.canary_name`** authorises nothing — it holds a nickname used as a
162
+ liveness marker. It is class B because it cannot be inferred and is worth
163
+ keeping once answered, and its disposition (`un-inferrable`) already says so.
164
+ There is no gate to build here and never was.
165
+ - **`personal.open_edited_files`** is a genuine `consent` key with **no mechanism
166
+ that can refuse the action** — its only reader is prose in
167
+ `src/skills/file-editor/SKILL.md`. The suite's standing rule is *never claim
168
+ enforcement you do not have*, and the discharge of that rule is to **declare
169
+ the limit**, not to delete the user's choice: it is carried as an explicitly
170
+ prose-only preference. An unenforceable flag that says it is unenforceable is
171
+ honest; one that presents as a gate is not.
172
+ - **`memory.learn_on_session_end`** is what a consent key looks like when the
173
+ mechanism exists: `src/scripts/memory_learn_hook.ts` reads it and can withhold
174
+ the write, and the default is conservative.
175
+
176
+ Splitting class B into `B-consent` and `B-config` was considered and **not
177
+ taken** — it would churn a contract, a linter and every consumer's mental model
178
+ to express what this paragraph expresses. What the split would have bought is
179
+ the obligation stated above; stating it directly costs one section.
180
+
181
+ **Consequence for anyone adding a class-B key:** the § B eligibility invariant
182
+ still binds in full. This section adds one question on top of it — *if the
183
+ disposition is `consent`, what can refuse the action?* An answer of "nothing"
184
+ is allowed, and must then be written down as such.
185
+
144
186
  ## The one exception — `emergency.orchestration_halt`
145
187
 
146
188
  The always-on-orchestration doctrine (subagents, council, team) deletes every
@@ -189,12 +231,15 @@ dispatch runs, not WHETHER the layer exists, so they keep their own C rows.
189
231
  |---|---|
190
232
  | A — preference | 26 |
191
233
  | B — consent | 3 |
192
- | C — guarded | 106 |
193
- | **Total** | **135** |
234
+ | C — guarded | 105 |
235
+ | **Total** | **134** |
194
236
 
195
237
  The total was 140 until 2026-08-12, when five of the six keys no code path read were
196
238
  deleted, minus the one held open (§ The six unread keys, below): one A
197
- (`telegraph.speak_scope`) and four C.
239
+ (`telegraph.speak_scope`) and four C. It dropped to 134 on 2026-08-13 when
240
+ ADR-229 deleted `worktrees.mode` — a fifth C, and the first deletion in this
241
+ series of a key that WAS read: the doctrine there is that the decision was never
242
+ the agent's to make, not that nothing consulted it.
198
243
 
199
244
  The total is every leaf in the template, where *leaf* means anything that is not
200
245
  a **non-empty** map. An empty map (like the former `subagents.host_capabilities: {}`) is a real
@@ -244,9 +289,9 @@ the template, which is the drift this contract exists to prevent.
244
289
  |---|---|
245
290
  | derivable | 83 |
246
291
  | un-inferrable | 9 |
247
- | consent | 38 |
292
+ | consent | 37 |
248
293
  | policy | 5 |
249
- | **Total** | **135** |
294
+ | **Total** | **134** |
250
295
 
251
296
  First measured 2026-08-12 at 140 leaves (derivable 88 · consent 38 ·
252
297
  un-inferrable 9 · policy 5), from the table below rather than predicted — the
@@ -421,7 +466,6 @@ Rows follow template order, so a diff against the template reads straight down.
421
466
  | `subagents.model_ceiling` | C | `""` | session-wide subagent model cap (exported as `CLAUDE_CODE_SUBAGENT_MODEL` by suite-owned CLI spawn wrappers), which is spend and quality | consent |
422
467
  | `subagents.max_parallel` | C | `3` | parallelism cap, and therefore a spend rate | consent |
423
468
  | `subagents.adversarial_council` | C | `"off"` | governs a paid verification step | consent |
424
- | `worktrees.mode` | C | `ask` | standing permission for autonomous worktree creation | consent |
425
469
  | `ai_team.model` | C | `auto` | names an external model | un-inferrable |
426
470
  | `ai_team.allow_delegate` | C | `false` | grants an external tool write access to the repository | consent |
427
471
  | `ai_team.max_calls_per_day` | C | `50` | quota cap on a shared budget | consent |
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": "10.4.0",
4
+ "version": "12.0.0",
5
5
  "description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) — every claim machine-checked, including \"zero runtime daemon\".",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -133,6 +133,40 @@ projection:
133
133
  # (vendor-granular unknown_defaults in src/config/host-capabilities.yml).
134
134
  discipline_profile: __DISCIPLINE_PROFILE__
135
135
 
136
+ # OPT-IN PRESET — the measured-lift configuration, shown but NOT shipped.
137
+ #
138
+ # The evidence above says `essential` carries the significant discipline lift
139
+ # (+0.458, p=0.0135) while `full`'s residual over it is not significant
140
+ # (p=0.37). That reads like an argument to flip the shipped default. It is not,
141
+ # for two independent reasons, and both are worth stating where the key lives
142
+ # rather than in a roadmap nobody reads at install time.
143
+ #
144
+ # 1. This key family is marked "do not set this from automation". That reads
145
+ # as ABSOLUTE — it forbids an automated CHOICE of default for the family,
146
+ # not merely a script rewriting your file. No measurement, however clean,
147
+ # licenses an agent to flip it on your behalf.
148
+ # 2. The flip was pre-registered against a fresh-install census of
149
+ # <= 30k tokens of always-on rule prose. Measured at audit time: ~163k as
150
+ # loaded, i.e. 5.4x the target. The criterion fails on its own terms
151
+ # regardless of point 1.
152
+ #
153
+ # So the better-evidenced value is carried here as a visible option you may
154
+ # uncomment, with its cost stated inline. Uncomment the line below to replace
155
+ # the resolved value above:
156
+ #
157
+ # discipline_profile: essential # ~3.3x kernel tokens (vs ~11.7x for full)
158
+ #
159
+ # Read the two factors as what they are: multiples of the kernel-only baseline
160
+ # from the cost-factor sweep, NOT the fresh-install census. They answer "what
161
+ # does this tier cost relative to `off`", never "does this tier reach 30k" —
162
+ # nothing has measured the latter for `essential`, and this comment does not
163
+ # claim it does.
164
+ #
165
+ # Recorded 2026-08-14 on an outside opinion (1 seat, 2 rounds; the second seat
166
+ # failed to start, so a single-model judgement on its checkable merit and NOT a
167
+ # convergence). It rejected both the flip and the do-nothing, and proposed this
168
+ # third route: you see the option, nothing automated chose for you.
169
+
136
170
  # --- Cost profile (legacy knob — superseded by discipline_profile above) ---
137
171
  #
138
172
  # Master switch that controls which rule tiers load each session.
@@ -815,24 +849,21 @@ subagents:
815
849
 
816
850
  # --- Git worktrees ---
817
851
  #
818
- # Controls how the `using-git-worktrees` skill and `subagent-orchestration`
819
- # mode 6 (`do-in-worktrees`) behave. Mechanical layer on top of the
820
- # existing `scope-control` permission gate — narrows, never widens.
821
- worktrees:
822
- # off | on | ask (default: ask)
823
- #
824
- # ask = status quo. Skill asks before creating any worktree; mode 6 is
825
- # selectable when the chain shape warrants it. Matches the
826
- # behaviour required by `scope-control` and `autonomous-execution`.
827
- # off = no autonomous worktree creation. Skill refuses; mode 6 falls
828
- # back to mode 3 (do-in-steps). Explicit user request in the
829
- # chat ("do this in a worktree", "use mode 6") overrides for
830
- # that single task — the setting suppresses *unprompted* usage,
831
- # not the tool itself.
832
- # on = standing permission. Skill skips the per-creation permission
833
- # ask; mode 6 may be picked without prompting. Iron-Law gates
834
- # (ignore-check, clean baseline) still apply.
835
- mode: ask
852
+ # There is no setting. Worktree creation is INSTRUCTION-ONLY (ADR-229):
853
+ # `using-git-worktrees` and `subagent-orchestration` mode 6 (`do-in-worktrees`)
854
+ # create a worktree ONLY when the user asks for one in the chat ("do this in a
855
+ # worktree", "use mode 6"). Unprompted, mode 6 is not selectable and the chain
856
+ # falls back to mode 3 (`do-in-steps`).
857
+ #
858
+ # `worktrees.mode` was DELETED. It offered `ask`/`on`/`off` over a decision that
859
+ # was never the agent's to make: `ask` spent a round trip on every spawn, `on`
860
+ # let the agent start parallel work on its own, and `off` was the behaviour
861
+ # everyone actually wanted — so the setting's only real value was hardcoded and
862
+ # the other two values removed. A leftover key from an older install is ignored
863
+ # with one deprecation line (see `REMOVED_KEYS` in `_lib/agent_settings.ts`).
864
+ #
865
+ # The Iron-Law gates on creation (ignore-safety check, clean baseline) are
866
+ # unchanged and still run on every explicitly-requested worktree.
836
867
 
837
868
  # --- AI Council (external second-opinion network) ---
838
869
  #
@@ -335,9 +335,19 @@ gates:
335
335
  Why 340 and not 360, the measured value: gate-authoring.md § registration
336
336
  requires a floor BELOW the live count, because a floor pinned at today's
337
337
  number reds on the very change that legitimately retires one unit. 340
338
- leaves ~20 units (~5.5%) of headroom while still catching the collapse this
339
- floor exists for — a re-broken extractor would drop the count by 164, not
340
- by 20.
338
+ leaves ~20 units (~5.5%) of headroom.
339
+ What this floor can and cannot catch, corrected after the R2 review caught
340
+ the first version arguing from a break that cannot fire it. The extraction
341
+ bug INFLATED the count — phantom gate names entering the CI set — so a
342
+ re-break raises the population to roughly 527 and a min_scanned floor never
343
+ triggers on a rise. The floor guards the opposite direction: an extractor
344
+ that stops finding taskfiles or workflows at all, a parse error zeroing one
345
+ side, a scan root that moves. Those are collapses of 100+ units and 340
346
+ catches every one of them. The realistic PARTIAL break — one taskfile
347
+ failing to parse, say ~14 units — passes 340 and would have failed 380,
348
+ which is the honest cost of the headroom and is accepted here rather than
349
+ hidden: a floor tight enough to catch that is also tight enough to red on
350
+ the next legitimate retirement.
341
351
 
342
352
  - id: check_site_links
343
353
  argv: []
@@ -4,13 +4,13 @@
4
4
  "ci-parity:local-only": {
5
5
  "count": 166,
6
6
  "landed": "2026-08-13",
7
- "note": "Gates that `task ci` runs and no workflow does — the direction this manifest's own header calls the one that let real defects merge (16 stale index rows reached the trunk behind a local-only check-index). Revealed, not created, by repairing the checker's extraction: check_ci_local_parity built its CI-side set by regexing RAW workflow text for `task <name>` and expanding each closure, comments included. Several workflow comments contain the literal string `task ci` while stating that no workflow invokes it, so `ci` was read as an invocation and its full 247-gate closure entered the 'runs in CI' set. The count was therefore 0 BY CONSTRUCTION, and the prose documenting the gap was what suppressed it. Measured at the repair: CI-side 273 → 106, undeclared_local_only 0 → 167 of 247 local gates (68%). Baselined rather than hard-failed because 167 findings nobody can clear in the change that reveals them is the gate-that-lands-as-N-instant-blockers failure this repository has refused before; shrink-only keeps the property that matters, namely that a NEW gate registered in `task ci` with no workflow reds immediately. Lowering happens by wiring gates into workflows or declaring them under `local_only:` with a reason. Note the punchline, because it bounds the risk of this entry: check_ci_local_parity ITSELF runs in no workflow, so it is its own finding and this ratchet has no remote reach either — clearing the backlog is what gives it teeth. DRAINED BY ONE, 2026-08-13: check_ci_local_parity itself was wired into consistency.yml, so it left the set it exists to report. That is the whole shape of a legitimate drain here — the gate stops being local-only because a workflow now runs it, not because the declaration list grew. The floor in gate-coverage.yml moved in the same change and for the same reason: wiring two gates raised the parsed population 357 -> 359.",
7
+ "note": "Gates that `task ci` runs and no workflow does — the direction this manifest's own header calls the one that let real defects merge (16 stale index rows reached the trunk behind a local-only check-index). Revealed, not created, by repairing the checker's extraction: check_ci_local_parity built its CI-side set by regexing RAW workflow text for `task <name>` and expanding each closure, comments included. Several workflow comments contain the literal string `task ci` while stating that no workflow invokes it, so `ci` was read as an invocation and its full 247-gate closure entered the 'runs in CI' set. The count was therefore 0 BY CONSTRUCTION, and the prose documenting the gap was what suppressed it. Measured at the repair: CI-side 273 → 106, undeclared_local_only 0 → 167 of 247 local gates (68%). Baselined rather than hard-failed because 167 findings nobody can clear in the change that reveals them is the gate-that-lands-as-N-instant-blockers failure this repository has refused before; shrink-only keeps the property that matters, namely that a NEW gate registered in `task ci` with no workflow reds immediately. Lowering happens by wiring gates into workflows or declaring them under `local_only:` with a reason. Note the punchline, because it bounds the risk of this entry: check_ci_local_parity ITSELF runs in no workflow, so it is its own finding and this ratchet has no remote reach either — clearing the backlog is what gives it teeth. DRAINED BY ONE, 2026-08-13: check_ci_local_parity itself was wired into consistency.yml, so it left the set it exists to report. That is the whole shape of a legitimate drain here — the gate stops being local-only because a workflow now runs it, not because the declaration list grew. The floor in gate-coverage.yml moved in the same change and for the same reason: wiring two gates raised the parsed population 357 -> 360 (109 CI + 251 local). The intermediate 359 was the reading after the CI-side wiring alone and before check_gate_coverage joined the local `ci` chain; it was committed here by mistake and is corrected rather than left as a second number for the same measurement.",
8
8
  "falsifier": "./scripts-run src/scripts/check_ci_local_parity"
9
9
  },
10
10
  "check_no_new_legacy_path:hardcoded-scan-roots": {
11
- "count": 48,
12
- "landed": "2026-08-09",
13
- "note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)` — a filesystem path CONSTRUCTED against the tree ADR-051 abandoned, which is the exact shape of all 14 dead gates. Deliberately narrow so the number is signal, not noise: 236 raw mentions under src/scripts → 147 string-literal lines → 67 path-constructing lines when the pass was written, after exempting src/scripts/_lib/agent_src.ts (the shared resolver, whose job IS owning the constant — gates that route through it survived the move). Detectors holding the literal as data to match, strip, or print are not counted, and no prose, docs, tests or fixtures are read: that full-tree shape was measured at 44 files / 213 hits and rejected as the wrong lint (see the note in check_no_new_legacy_path.ts::find_offenders). Recorded at 58 rather than 67 because Phase 1's scan-root repairs were landing on this branch while the pass was being written and had already removed 9 — a baseline above the truth silently permits new violations. This count goes to ZERO as the remaining repairs land; every repair is a lowering commit. Lowered 56→51 by the road-to-renewal-foundation Phase 1 dead-root sweep (check_always_budget, check_portability, check_references, lint_framework_leakage, lint_agents_md). Lowered 51→49 by the gate-hardening adoption PR: skill_collision_clusters and skill_overlap were repointed at the live skills tree via the shared resolver — two gates that had been reading the retired container and scoring 0 of 288 skills. Lowered 49→48 by road-to-rule-delivery-integrity P2.2: score_skill_selection was repointed at the live skills tree via the shared resolver. It is the same shape as the two gates lowered before it — a scorer reading the retired container and scoring 0 of 288 skills — and here the consequence was sharper than a dead gate: the roadmap's pre-registered selection-accuracy criteria would have been compared against a baseline of silent zeros."
11
+ "count": 47,
12
+ "landed": "2026-08-13",
13
+ "note": "Lines under src/scripts/**/*.{ts,mts,mjs} that pass the retired `.agent-src.uncondensed` directory into `path.join(...)` — a filesystem path CONSTRUCTED against the tree ADR-051 abandoned, which is the exact shape of all 14 dead gates. Deliberately narrow so the number is signal, not noise: 236 raw mentions under src/scripts → 147 string-literal lines → 67 path-constructing lines when the pass was written, after exempting src/scripts/_lib/agent_src.ts (the shared resolver, whose job IS owning the constant — gates that route through it survived the move). Detectors holding the literal as data to match, strip, or print are not counted, and no prose, docs, tests or fixtures are read: that full-tree shape was measured at 44 files / 213 hits and rejected as the wrong lint (see the note in check_no_new_legacy_path.ts::find_offenders). Recorded at 58 rather than 67 because Phase 1's scan-root repairs were landing on this branch while the pass was being written and had already removed 9 — a baseline above the truth silently permits new violations. This count goes to ZERO as the remaining repairs land; every repair is a lowering commit. Lowered 56→51 by the road-to-renewal-foundation Phase 1 dead-root sweep (check_always_budget, check_portability, check_references, lint_framework_leakage, lint_agents_md). Lowered 51→49 by the gate-hardening adoption PR: skill_collision_clusters and skill_overlap were repointed at the live skills tree via the shared resolver — two gates that had been reading the retired container and scoring 0 of 288 skills. Lowered 49→48 by road-to-rule-delivery-integrity P2.2: score_skill_selection was repointed at the live skills tree via the shared resolver. It is the same shape as the two gates lowered before it — a scorer reading the retired container and scoring 0 of 288 skills — and here the consequence was sharper than a dead gate: the roadmap's pre-registered selection-accuracy criteria would have been compared against a baseline of silent zeros. Lowered 48→47 on 2026-08-13, and this one is a catch-up rather than a repair: the pass reported 47 against a baseline of 48, so a gain had already landed without the ratchet following it. Attributed to 455160160 (fix(evals): resolve the eval orchestrator against the live skills tree), the most recent repair in this branch's base that removes a path-constructing line — SKILLS_ROOT repointed through _lib/agent_src.ts::SRC_SKILLS(). A loose ratchet is not harmless: it silently permits one new violation to be added back without any gate noticing, which is the shape this entry exists to prevent."
14
14
  },
15
15
  "audit_user_type_axis": {
16
16
  "count": 1,
@@ -20,9 +20,10 @@
20
20
  "rationale": "Measured 2026-07-31: the largest non-excepted skill is corpus-grounding at 2.33%, so a 5% cap is green with better than 2x headroom and red for any skill that doubles. It is a falsifiable gate, not a ritual one.",
21
21
  "exceptions": {
22
22
  "design-intelligence": {
23
- "max_pct": 23.0,
23
+ "max_pct": 23.5,
24
24
  "measured_pct": 22.63,
25
- "reason": "771 KB of BM25 corpus (27 CSVs + 16 design-language prose specs + manifest.json) consumed at runtime by corpus-grounding's retriever, and referenced by 6 further skills. Moving it behind a lazy fetch would add a network dependency to a skill that works offline today — the same trade-off ADR-061 §8 already REJECTED for a 745 KB font index. The exception is visible debt, not an endorsement: raising max_pct requires a reason in the same commit."
25
+ "reason": "771 KB of BM25 corpus (27 CSVs + 16 design-language prose specs + manifest.json) consumed at runtime by corpus-grounding's retriever, and referenced by 6 further skills. Moving it behind a lazy fetch would add a network dependency to a skill that works offline today — the same trade-off ADR-061 §8 already REJECTED for a 745 KB font index. The exception is visible debt, not an endorsement: raising max_pct requires a reason in the same commit.",
26
+ "baseline_note_2026_08_13": "23.0 → 23.5 on 2026-08-13, and the reason belongs in this file per the sentence above. WHAT WAS ADOPTED: data/motion.csv, 10.5 KB, 16 rows. WHY IT IS NOT DISCRETIONARY: the roadmap's three design dials were all in its original scope, and two of the three (variance, density) were already portable — variance's keywords resolve against the local styles.csv (2/3/3 hits) and density is three pure range maps. The motion dial is not: upstream filters its corpus rows by `Intensity Tier == <dial tier>`, and that column exists only in motion.csv, so shipping the dial without the file means shipping a flag that silently does nothing. Two of three dials plus an inert third is a worse surface than three working ones. WHAT WAS DECLINED IN THE SAME PASS, so this is not a ratchet slipping: google-fonts.csv (743 KB — ADR-061 §8 rejects it by name and by size; the 2026-06-16 amendment authorises a slim top-N slice from a different mirror, not this file), typography.csv (our curated font-pairings-reference.csv is the ADR's working substitution), six desktop-UI stacks outside frontend-design's scope, and eleven content-drifted files nobody has reviewed. The base pin in ATTRIBUTION.md is deliberately NOT bumped for the same reason. HONEST LIMIT ON THE NUMBER: 22.63 is the committed measurement, not a fresh one — check_pack_size cannot be re-measured from a built worktree (it reads 9.096 against the 7.8 packed cap before any change, the trap the packed_size_mb note above documents), so the post-adoption share is arithmetic (~22.87 %) and the new cap carries ~0.6 pp over it rather than clearing by a hair. DECIDED BY: AI council, 2026-08-13, on a maintainer delegation — and honestly, by ONE member over two rounds, not by convergence: the second seat returned exit_1 (the codex CLI refuses a git worktree as an untrusted directory). Recorded as a single-member review in agents/evidence/analysis/design-system-blockers-council.md."
26
27
  }
27
28
  }
28
29
  }
@@ -447,6 +447,9 @@ require_tsx() {
447
447
  # command surface (`sync`, `doctor`, `validate`, `upgrade`, …) and its
448
448
  # basenames are unique, so the mapping is collision-free. Other exec_ts
449
449
  # callers (resolve_script results, the work engine, …) are unaffected.
450
+ #
451
+ # In a DEV tree the bundle is also suppressed when any `src/**/*.ts` is newer
452
+ # than it — see cli_delegate_bundle_is_stale.
450
453
  cli_delegate_bundle() {
451
454
  local ts_abs="$1"
452
455
  case "$ts_abs" in
@@ -457,18 +460,52 @@ cli_delegate_bundle() {
457
460
  name="$(basename "${ts_abs%.ts}")"
458
461
  local bundle="$PACKAGE_ROOT/dist/cli-delegate/$name.js"
459
462
  if [[ -f "$bundle" ]] && command -v node >/dev/null 2>&1; then
463
+ cli_delegate_bundle_is_stale "$bundle" && return 0
460
464
  printf '%s' "$bundle"
461
465
  fi
462
466
  }
463
467
 
468
+ # Is a `dist/cli-delegate/` bundle older than the sources it was built from?
469
+ #
470
+ # Only asked in a DEV tree — `$PACKAGE_ROOT/src` exists there and nowhere else.
471
+ # A consumer install ships no `src/`, so it returns "not stale" without a single
472
+ # stat and the ADR-204 fast path is untouched.
473
+ #
474
+ # The scan covers `src` WHOLE, not `src/scripts`: `_cli/*.ts` imports reach into
475
+ # `src/shared`, `src/install`, `src/server`, `src/agent`, `src/config` and
476
+ # `src/agent-src`, and the defect this guard exists for lived two hops away in
477
+ # `src/scripts/_lib/cc_transcript.ts` — a scan narrowed to the entry point's own
478
+ # directory would have missed it.
479
+ #
480
+ # Cost, measured 2026-08-14 on the local tree (1075 `.ts` files): 78 ms when the
481
+ # bundle is current (the full walk) and ~12 ms when it is not (`-quit` exits at
482
+ # the first newer file). The bundle saves ~290 ms against the tsx path, so the
483
+ # worst case still leaves most of that — and buys the guarantee that a dev-tree
484
+ # edit is never silently ignored in favour of a stale compile.
485
+ cli_delegate_bundle_is_stale() {
486
+ local bundle="$1"
487
+ [[ -d "$PACKAGE_ROOT/src" ]] || return 1
488
+ local newer
489
+ newer="$(find "$PACKAGE_ROOT/src" -name '*.ts' -newer "$bundle" -print -quit 2>/dev/null)"
490
+ [[ -n "$newer" ]]
491
+ }
492
+
464
493
  # Run an absolute script path. The argument is an absolute path that may carry
465
494
  # a `.py` (legacy) or `.ts` extension; we resolve the `.ts` twin.
466
495
  #
467
- # A precompiled `dist/cli-delegate/` bundle wins when present — the consumer
468
- # tree ships no tsx (see require_tsx), and the bundle is also ~5.7x faster
469
- # than the npx path it replaces (p50 56-71 ms vs 346-392 ms, measured
470
- # 2026-07-31; see docs/decisions/ADR-204). The tsx path stays as the dev-tree
471
- # route and as the fallback for every non-`_cli` caller.
496
+ # A precompiled `dist/cli-delegate/` bundle wins when present AND not stale —
497
+ # the consumer tree ships no tsx (see require_tsx), and the bundle is also
498
+ # ~5.7x faster than the npx path it replaces (p50 56-71 ms vs 346-392 ms,
499
+ # measured 2026-07-31; see docs/decisions/ADR-204). The tsx path stays as the
500
+ # dev-tree route and as the fallback for every non-`_cli` caller.
501
+ #
502
+ # "Not stale" is the load-bearing qualifier, and it was added because the
503
+ # unqualified version shipped a real failure: a dev-tree `dist/cli-delegate/`
504
+ # built before a `projectStoreSlug` fix kept running the OLD slug, so
505
+ # `agent-config handoff --list` reported "no recent sessions" in any worktree
506
+ # whose path carried a `+`, while the fixed source right next to it listed ten.
507
+ # A compiled copy that silently outranks the source it was built from turns
508
+ # every edit into a coin flip — see cli_delegate_bundle_is_stale.
472
509
  #
473
510
  # Argv/stdin/stdout/stderr/exit-code pass through unchanged in both routes —
474
511
  # mirrors src/scripts/run.ts resolution.
@@ -922,6 +922,13 @@ export function load_agent_settings(
922
922
  * whether the repair is to build its missing reader or to delete a promise a
923
923
  * Hard Floor can never honour. See `settings-classes.md` § The six unread keys.
924
924
  *
925
+ * `worktrees.mode` (2026-08-13, ADR-229) is a third doctrine again: not
926
+ * always-on, not unread. It WAS read, and the reader honoured all three values —
927
+ * the deletion says the decision was never the agent's to make. `ask` bought a
928
+ * round trip per spawn, `on` let the agent start parallel work unprompted, and
929
+ * `off` described the wanted behaviour, so `off` became the hardcoded rule and
930
+ * the switch went. What decides instead is the user's own sentence in the chat.
931
+ *
925
932
  * Every reason string must name what decides INSTEAD, never just "removed".
926
933
  * Exported so `lint_settings_classes` can check the deletion side of the
927
934
  * surface: a reason that names no replacement, or an entry whose key is live in
@@ -942,6 +949,7 @@ export const REMOVED_KEYS: ReadonlyMap<string, string> = new Map([
942
949
  ['chat_history.on_overflow', 'the overflow mode comes from the rotate command --mode argv'],
943
950
  ['quality.wait_for_remote_ci', 'whether to poll follows from the push plus a detectable remote pipeline'],
944
951
  ['legal_review_prep.consented_at', 'the provenance sidecar settings:set writes and consentVerdict reads'],
952
+ ['worktrees.mode', 'the user asking for a worktree in the chat; creation is instruction-only and hardcoded'],
945
953
  ]);
946
954
 
947
955
  /** Keys already warned about in THIS process — the "once per run" dedupe. */
@@ -57,9 +57,14 @@ const SIZE_BUDGETS: Record<string, number> = {
57
57
  platform: 10,
58
58
  };
59
59
  // ADR-092: `visibility:` is the named source of truth (visible / advanced /
60
- // internal); the integer `tier:` is a back-compat alias. A command counts
61
- // toward the per-pack budget when it is surfaced — visibility in {visible,
62
- // advanced} (or, when only the alias is present, tier in {0,1}). `internal`
60
+ // internal). The integer `tier:` alias was REMOVED from live command files in
61
+ // road-to-tier-removal Phase 4, but this file still parses it on purpose: the
62
+ // surface-growth check reads PAST git revisions (`_tier_at_ref`), and pre-ADR-092
63
+ // blobs carry only the alias. The live-file tier read below is therefore a
64
+ // harmless residue on current files and the correct read on historical ones.
65
+ // A command counts toward the per-pack budget when it is surfaced — visibility
66
+ // in {visible, advanced} (or, when only the alias is present, tier in {0,1}).
67
+ // `internal`
63
68
  // (or absent → defaults to internal) is uncapped.
64
69
  const VISIBLE_TIERS: ReadonlySet<number> = new Set([0, 1]);
65
70
  const VISIBLE_VISIBILITIES: ReadonlySet<string> = new Set(['visible', 'advanced']);
@@ -622,17 +627,17 @@ export function render_md(commands: Command[], pairs: OverlapPair[]): string {
622
627
  '[`command-surface-synthesis.md`](command-surface-synthesis.md). Every command ' +
623
628
  "in this table maps to `keep` unless named in that file's tables.",
624
629
  '',
625
- '| Name | Path | Tier | Cluster | Aliases | Lines | Commits | Age (d) | Bucket |',
630
+ '| Name | Path | Visibility | Cluster | Aliases | Lines | Commits | Age (d) | Bucket |',
626
631
  '|---|---|---:|---|---|---:|---:|---:|---|',
627
632
  );
628
633
  const sortedCmds = _stableSortStr(commands, (c) => c.relpath);
629
634
  for (const c of sortedCmds) {
630
635
  const aliases = c.aliases.length ? c.aliases.join(', ') : '—';
631
- const tier = c.tier === null ? '—' : String(c.tier);
636
+ const visibility = c.visibility === null ? '—' : c.visibility;
632
637
  const cluster = c.cluster || '—';
633
638
  const age = c.days_since_first_commit === null ? '—' : String(c.days_since_first_commit);
634
639
  lines.push(
635
- `| \`${c.name}\` | \`${c.relpath}\` | ${tier} | ${cluster} | ${aliases} | ` +
640
+ `| \`${c.name}\` | \`${c.relpath}\` | ${visibility} | ${cluster} | ${aliases} | ` +
636
641
  `${c.line_count} | ${c.commit_count} | ${age} | |`,
637
642
  );
638
643
  }
@@ -738,7 +743,7 @@ function _is_visible(c: Command): boolean {
738
743
 
739
744
  interface VisibleCommand {
740
745
  name: string;
741
- tier: number | null;
746
+ visibility: string | null;
742
747
  cluster: string;
743
748
  citations_docs: number;
744
749
  commit_count: number;
@@ -797,7 +802,7 @@ export function build_budget_audit(
797
802
  if (over) {
798
803
  const vis = visible.map((c) => ({
799
804
  name: c.name,
800
- tier: c.tier,
805
+ visibility: c.visibility,
801
806
  cluster: c.cluster,
802
807
  citations_docs: citation_count(c.name),
803
808
  commit_count: c.commit_count,
@@ -832,8 +837,9 @@ export function render_budget_md(audit: BudgetAudit): string {
832
837
  L.push('# Command budget audit (6.0.0-B Phase 2 Step 4)\n');
833
838
  L.push(
834
839
  '> Per-pack VISIBLE-command counts vs. the `size_class` budget ' +
835
- '(capability-packs.md). `visible` = tier ∈ {0,1}; tier 2 / absent = ' +
836
- 'internal (uncapped). Citations = docs/ files referencing `/<name>`.\n' +
840
+ '(capability-packs.md). `visible` = visibility ∈ {visible, advanced}; ' +
841
+ '`internal` / absent = uncapped. Citations = docs/ files referencing ' +
842
+ '`/<name>`.\n' +
837
843
  '>\n' +
838
844
  '> **Signal note:** docs-citations is the load-bearing signal (rank ' +
839
845
  'candidates low→high). The git commit/idle columns are low-variance on ' +
@@ -862,11 +868,11 @@ export function render_budget_md(audit: BudgetAudit): string {
862
868
  `budget ${p.budget} (${p.size_class}), over by ${p.over_by}\n`,
863
869
  );
864
870
  L.push('Decide per command: keep-visible · set `internal` · relocate-to-pack-X.\n');
865
- L.push('| Command | tier | cluster | docs citations | commits | days idle |');
866
- L.push('|---|--:|---|--:|--:|--:|');
871
+ L.push('| Command | visibility | cluster | docs citations | commits | days idle |');
872
+ L.push('|---|---|---|--:|--:|--:|');
867
873
  for (const c of p.visible_commands ?? []) {
868
874
  L.push(
869
- `| \`${c.name}\` | ${c.tier} | ${c.cluster || '—'} | ` +
875
+ `| \`${c.name}\` | ${c.visibility ?? '—'} | ${c.cluster || '—'} | ` +
870
876
  `${c.citations_docs} | ${c.commit_count} | ` +
871
877
  `${c.days_since_modified !== null ? c.days_since_modified : '—'} |`,
872
878
  );
@@ -1050,8 +1056,8 @@ export function check_new_budget(baseline: string, quiet: boolean): number {
1050
1056
  );
1051
1057
  }
1052
1058
  process.stdout.write(
1053
- '\nResolve by one of: set the command to `tier: 2` (internal, ' +
1054
- 'uncapped) · merge into a sibling cluster · relocate to a pack ' +
1059
+ '\nResolve by one of: set the command to `visibility: internal` ' +
1060
+ '(uncapped) · merge into a sibling cluster · relocate to a pack ' +
1055
1061
  'with budget headroom · file a budget-exemption ADR ' +
1056
1062
  '(docs/contracts/capability-packs.md § Budget exemption process).\n',
1057
1063
  );
@@ -138,7 +138,7 @@ export function buildEntries(): CatalogIndexEntry[] {
138
138
  cls: 'command',
139
139
  name,
140
140
  description: _str(fm['description']) || _str(fm['intent']),
141
- tags: [_str(fm['pack']), _str(fm['tier']), _str(fm['visibility'])].filter((s) => s.length > 0),
141
+ tags: [_str(fm['pack']), _str(fm['visibility'])].filter((s) => s.length > 0),
142
142
  path: _rel(abs),
143
143
  });
144
144
  }
@@ -657,26 +657,13 @@ function _build(strict: boolean): [JsonObject, JsonObject[]] {
657
657
  // 6.0.0-C: surface command routing metadata. Does not affect the
658
658
  // per-file checksum (computed over frontmatter, below).
659
659
  if (category === 'command' && fm !== null && _isObject(fm)) {
660
- if (fm['tier'] !== undefined && fm['tier'] !== null) {
661
- entry['tier'] = fm['tier'];
662
- }
663
- // ADR-090: `visibility:` is the named source of truth; the integer
664
- // `tier:` is a back-compat alias. Dual-emit BOTH into the manifest
665
- // (a published data contract) during the deprecation window so
666
- // external consumers reading the integer key keep working. The
667
- // top-level `deprecations` block (ADR-092 / road-to-tier-removal)
668
- // announces the `tier` deprecation; removal is Phase 4. Prefer the
669
- // explicit field; derive from tier when absent.
670
- const _tierToVis: Record<number, string> = { 0: 'visible', 1: 'advanced', 2: 'internal' };
671
- let _vis: Json = fm['visibility'];
672
- if (
673
- (_vis === undefined || _vis === null) &&
674
- fm['tier'] !== undefined &&
675
- fm['tier'] !== null
676
- ) {
677
- // `.get(fm["tier"])` returns None when tier is not 0/1/2 → undefined here.
678
- _vis = typeof fm['tier'] === 'number' ? _tierToVis[fm['tier']] : undefined;
679
- }
660
+ // ADR-090 named `visibility:` the source of truth; the integer
661
+ // `tier:` alias it superseded was dual-emitted here through the
662
+ // deprecation window and REMOVED in road-to-tier-removal Phase 4.
663
+ // The manifest no longer carries `tier` in any entry — the
664
+ // top-level `deprecations` block records the removal for consumers
665
+ // that still read the old key.
666
+ const _vis: Json = fm['visibility'];
680
667
  if (_vis !== undefined && _vis !== null) {
681
668
  entry['visibility'] = _vis;
682
669
  }
@@ -788,27 +775,36 @@ function _build(strict: boolean): [JsonObject, JsonObject[]] {
788
775
  const stats = _compute_stats(artefacts, unassigned, documentedUnassigned);
789
776
 
790
777
  const manifest: JsonObject = {
791
- version: 2,
792
- // Machine-readable deprecation signal (road-to-tier-removal Phase 1,
793
- // ADR-092). The integer command `tier` (0/1/2) is a back-compat alias
794
- // for the named `visibility` field (ADR-090). It is STILL emitted into
795
- // command entries above (non-breaking) — this block only ANNOUNCES the
796
- // deprecation so external manifest consumers can migrate to `visibility`
797
- // during the soak window. Removal of `tier` is Phase 4 of
798
- // road-to-tier-removal (cheaply reversible per ADR-092); `sunset` is
799
- // maintainer-owned and stays null until the soak clears.
778
+ // v3 (road-to-tier-removal Phase 4): the integer command `tier` is no
779
+ // longer emitted on `category: command` artefacts. That is a breaking
780
+ // change to a published data contract, and this schema's own rule is
781
+ // "bump on breaking change" — so the version carries the break rather
782
+ // than leaving a v2 consumer to discover a silently-absent field.
783
+ version: 3,
784
+ // Machine-readable removal record (road-to-tier-removal Phase 1 added
785
+ // this block as a deprecation ANNOUNCEMENT; Phase 4 turned it into the
786
+ // record of an executed removal). The entry is retained on purpose: a
787
+ // consumer that still reads the old key needs to find out what replaced
788
+ // it and when it went, and an absent entry would say neither. `sunset`
789
+ // is maintainer-owned: SET on 2026-08-13, with the soak wait explicitly
790
+ // waived ("wir haben lange genug gewartet"). ADR-137 had already reduced
791
+ // the re-open trigger set to this one act — a concrete sunset — after
792
+ // withdrawing the second trigger as structurally impossible in a
793
+ // no-runtime package.
800
794
  deprecations: [
801
795
  {
802
796
  key: 'tier',
803
797
  scope: 'command',
804
798
  replacement: 'visibility',
805
799
  since: 'ADR-092',
806
- sunset: null,
800
+ sunset: '2026-08-13',
801
+ removed_in: 3,
807
802
  note:
808
- 'Integer command `tier` (0/1/2) is a deprecated back-compat ' +
809
- 'alias for the named `visibility` field (ADR-090). Read ' +
810
- '`visibility`; `tier` is still emitted (non-breaking) but ' +
811
- 'scheduled for removal — see road-to-tier-removal.',
803
+ 'Integer command `tier` (0/1/2) was a back-compat alias for ' +
804
+ 'the named `visibility` field (ADR-090). REMOVED in manifest ' +
805
+ 'v3 — command artefacts no longer carry `tier`. Read ' +
806
+ '`visibility` (`visible` / `advanced` / `internal`); the old ' +
807
+ 'mapping was 0↔visible, 1↔advanced, 2↔internal.',
812
808
  },
813
809
  ],
814
810
  generated_at: _nowUtc(),