@event4u/agent-config 14.12.0 → 14.13.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 (466) 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 +234 -0
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +109 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-provenance.md +4 -0
  30. package/dist/agent-src/rules/design-fidelity.md +1 -1
  31. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  32. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  33. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  34. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  35. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  36. package/dist/agent-src/rules/laravel-routing.md +1 -1
  37. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  38. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  39. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  40. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  41. package/dist/agent-src/rules/symfony-routing.md +1 -1
  42. package/dist/agent-src/rules/token-efficiency.md +14 -0
  43. package/dist/agent-src/rules/tool-safety.md +4 -0
  44. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  45. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  46. package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
  47. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  48. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  49. package/dist/agent-src/scripts/stubs_due.ts +400 -0
  50. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  51. package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
  52. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  53. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  54. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  55. package/dist/agent-src/skills/database/SKILL.md +8 -0
  56. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  58. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  60. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  61. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  62. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  63. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  64. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  65. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  66. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  67. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  68. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  69. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  70. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  71. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  72. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  73. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  74. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  75. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  76. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  77. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  78. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  79. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  80. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  81. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  82. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  83. package/dist/agent-src/templates/roadmaps.md +97 -3
  84. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  85. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  86. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  87. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  88. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  93. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  94. package/dist/cli/commands/uiAudit.js +124 -5
  95. package/dist/cli/registry.js +2 -0
  96. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  97. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  98. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  99. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  100. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  101. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  102. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  103. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  104. package/dist/cli-delegate/cmd_conformance.js +42 -10
  105. package/dist/cli-delegate/cmd_doctor.js +3 -3
  106. package/dist/cli-delegate/cmd_export.js +3 -2
  107. package/dist/cli-delegate/cmd_fleet.js +2 -2
  108. package/dist/cli-delegate/cmd_handoff.js +1 -1
  109. package/dist/cli-delegate/cmd_preflight.js +2 -2
  110. package/dist/cli-delegate/cmd_prune.js +3 -2
  111. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  112. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  113. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  114. package/dist/cli-delegate/cmd_sync.js +3 -2
  115. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  116. package/dist/cli-delegate/cmd_validate.js +3 -2
  117. package/dist/discovery/deprecation-report.md +1 -1
  118. package/dist/discovery/discovery-manifest.json +57 -57
  119. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  120. package/dist/discovery/discovery-manifest.summary.md +1 -1
  121. package/dist/discovery/dormancy-report.md +1 -1
  122. package/dist/discovery/orphan-report.md +1 -1
  123. package/dist/discovery/packs.json +2 -2
  124. package/dist/discovery/trust-report.md +1 -1
  125. package/dist/discovery/workspaces.json +2 -2
  126. package/dist/hooks/dispatch.js +1836 -712
  127. package/dist/install/claudeRuleRewrite.js +254 -0
  128. package/dist/install/detect.js +29 -16
  129. package/dist/install/detect_php_shape.js +159 -0
  130. package/dist/install/install.mjs +634 -428
  131. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  132. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  133. package/dist/mcp/registry-manifest.json +3 -3
  134. package/dist/mcp/server.json +3 -3
  135. package/dist/mcp/server.mjs +4818 -2645
  136. package/dist/server/schemas/settings.js +3 -0
  137. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  138. package/dist/ui/index.html +1 -1
  139. package/docs/MIGRATION.md +1 -1
  140. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  141. package/docs/contracts/provider-lifecycle.md +1 -1
  142. package/docs/contracts/settings-classes.md +10 -4
  143. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  144. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  145. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  146. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  147. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  148. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  149. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  150. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  151. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  152. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  153. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  154. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  155. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  156. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  157. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  158. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  159. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  160. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  161. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  162. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  163. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  164. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  165. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  166. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  167. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  168. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  169. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  170. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  171. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  172. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  173. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  174. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  175. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  176. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  177. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  178. package/docs/guidelines/augment-portability-patterns.md +6 -4
  179. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  180. package/docs/guidelines/cross-role-handoff.md +2 -2
  181. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  182. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  183. package/docs/guidelines/php/database.md +90 -7
  184. package/docs/guidelines/prompt-templates.md +7 -7
  185. package/llms.txt +2 -2
  186. package/package.json +5 -2
  187. package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  188. package/src/agent-src/scripts/guarded_baseline.ts +328 -0
  189. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  190. package/src/agent-src/scripts/stub_queue.ts +82 -0
  191. package/src/agent-src/scripts/stubs_due.ts +400 -0
  192. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  193. package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
  194. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  195. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  196. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  197. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  198. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  199. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  202. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  203. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  204. package/src/config/agent-settings.template.yml +32 -3
  205. package/src/config/assurance-capability-registry.json +21 -9
  206. package/src/config/canonical-terms.yml +119 -0
  207. package/src/config/capability-native-outcome-bars.json +81 -0
  208. package/src/config/ci-local-parity.yml +80 -0
  209. package/src/config/drafting-channels.yml +43 -0
  210. package/src/config/estate-count-budget.json +38 -36
  211. package/src/config/evaluator-budgets.json +14 -14
  212. package/src/config/gate-coverage.yml +579 -63
  213. package/src/config/gate-reachability-exemptions.json +21 -0
  214. package/src/config/gate-violation-baselines.json +37 -19
  215. package/src/config/harness-evolution-budget.json +25 -0
  216. package/src/config/lapsed-beta-baseline.json +96 -0
  217. package/src/config/memory-twin-verdicts.yml +129 -0
  218. package/src/config/metric-registry.yml +124 -0
  219. package/src/config/pack-size-budget.json +16 -15
  220. package/src/config/preamble-payload-budget.json +8 -8
  221. package/src/config/profiles/balanced.ini +27 -0
  222. package/src/config/profiles/full.ini +27 -0
  223. package/src/config/profiles/minimal.ini +27 -0
  224. package/src/config/publish-surface.json +9 -2
  225. package/src/config/routing-coverage-seed.json +16 -2
  226. package/src/config/rule-stub-ceilings.json +126 -112
  227. package/src/config/turnaround-budget.json +66 -0
  228. package/src/install/claudeRuleRewrite.ts +288 -0
  229. package/src/install/detect.ts +60 -17
  230. package/src/install/detect_php_shape.ts +191 -0
  231. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  232. package/src/scripts/_dispatch.bash +27 -0
  233. package/src/scripts/_lib/activation_ladder.ts +211 -0
  234. package/src/scripts/_lib/activation_states.ts +88 -0
  235. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  236. package/src/scripts/_lib/arith_claims.ts +181 -0
  237. package/src/scripts/_lib/arm_ranking.ts +62 -0
  238. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  239. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  240. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  241. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  242. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  243. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  244. package/src/scripts/_lib/candidate_record.ts +601 -0
  245. package/src/scripts/_lib/capture_rate.ts +319 -0
  246. package/src/scripts/_lib/collector_denominator.ts +771 -0
  247. package/src/scripts/_lib/collector_record.ts +340 -0
  248. package/src/scripts/_lib/collector_store.ts +664 -0
  249. package/src/scripts/_lib/collector_supervision.ts +827 -0
  250. package/src/scripts/_lib/concern_estate.ts +77 -0
  251. package/src/scripts/_lib/config_chain.ts +477 -0
  252. package/src/scripts/_lib/config_cost.ts +209 -0
  253. package/src/scripts/_lib/council_settings_block.ts +6 -0
  254. package/src/scripts/_lib/curator_ops.ts +172 -0
  255. package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
  256. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  257. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  258. package/src/scripts/_lib/empty_cycles.ts +88 -0
  259. package/src/scripts/_lib/eval_publication.ts +354 -0
  260. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  261. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  262. package/src/scripts/_lib/evidence_basis.ts +118 -0
  263. package/src/scripts/_lib/exec_evidence.ts +8 -0
  264. package/src/scripts/_lib/experience_card.ts +272 -0
  265. package/src/scripts/_lib/experience_report.ts +151 -0
  266. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  267. package/src/scripts/_lib/generated_by.ts +66 -0
  268. package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
  269. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  270. package/src/scripts/_lib/host_denominator.ts +687 -0
  271. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  272. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  273. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  274. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  275. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  276. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  277. package/src/scripts/_lib/loop_guards.ts +299 -0
  278. package/src/scripts/_lib/loss_class.ts +129 -0
  279. package/src/scripts/_lib/machine_wake.ts +51 -0
  280. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  281. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  282. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  283. package/src/scripts/_lib/orchestration_record.ts +253 -5
  284. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  285. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  286. package/src/scripts/_lib/paired_stats.ts +245 -0
  287. package/src/scripts/_lib/paired_verdict.ts +226 -0
  288. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  289. package/src/scripts/_lib/privacy_class.ts +47 -0
  290. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  291. package/src/scripts/_lib/repeated_failure.ts +105 -0
  292. package/src/scripts/_lib/repo_root.ts +111 -0
  293. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  294. package/src/scripts/_lib/role_split.ts +338 -0
  295. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  296. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  297. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  298. package/src/scripts/_lib/source_digest.ts +200 -0
  299. package/src/scripts/_lib/source_redact.ts +260 -0
  300. package/src/scripts/_lib/source_shape.ts +502 -0
  301. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  302. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  303. package/src/scripts/_lib/strip_comments.mjs +65 -0
  304. package/src/scripts/_lib/test_red_state.ts +154 -0
  305. package/src/scripts/_lib/trigger_shift.ts +144 -0
  306. package/src/scripts/_lib/untrusted_content.ts +82 -7
  307. package/src/scripts/adoption_report.ts +1 -1
  308. package/src/scripts/adr/evidence_census.ts +1 -1
  309. package/src/scripts/adr/regenerate_index.ts +26 -2
  310. package/src/scripts/adr_cite_check.ts +164 -1
  311. package/src/scripts/ai_council/blind_review.ts +11 -1
  312. package/src/scripts/ai_council/clients.ts +4 -0
  313. package/src/scripts/ai_council/config.ts +3 -0
  314. package/src/scripts/ai_council/consensus.ts +28 -8
  315. package/src/scripts/ai_council/consensus_round.ts +226 -0
  316. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  317. package/src/scripts/ai_council/inline_findings.ts +340 -0
  318. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  319. package/src/scripts/ai_council/orchestrator.ts +16 -203
  320. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  321. package/src/scripts/ai_council/pricing.ts +106 -0
  322. package/src/scripts/ai_council/prompts.ts +74 -7
  323. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  324. package/src/scripts/ai_council/py_format.ts +14 -3
  325. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  326. package/src/scripts/ai_council/response_record.ts +50 -0
  327. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  328. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  329. package/src/scripts/asset_delivery_ledger.ts +157 -0
  330. package/src/scripts/attest_artifact.ts +193 -0
  331. package/src/scripts/audit_auto_rules.ts +2 -1
  332. package/src/scripts/audit_command_surface.ts +1 -1
  333. package/src/scripts/audit_mcp_tools.ts +2 -2
  334. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  335. package/src/scripts/audit_user_type_axis.ts +2 -1
  336. package/src/scripts/bench_ab_clone.ts +215 -10
  337. package/src/scripts/bench_ab_integrity.ts +119 -5
  338. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  339. package/src/scripts/build_archive_index.ts +1 -1
  340. package/src/scripts/build_linear_digest.ts +1 -1
  341. package/src/scripts/build_proof.ts +11 -4
  342. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  343. package/src/scripts/build_source_digests.ts +157 -0
  344. package/src/scripts/cache_realization_report.ts +103 -0
  345. package/src/scripts/check_adr_frontmatter.ts +126 -0
  346. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  347. package/src/scripts/check_beta_review_markers.ts +235 -6
  348. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  349. package/src/scripts/check_claims.ts +576 -6
  350. package/src/scripts/check_composite_arming.ts +35 -0
  351. package/src/scripts/check_concern_admissions.ts +365 -0
  352. package/src/scripts/check_enforcement_coverage.ts +28 -0
  353. package/src/scripts/check_estate_count.ts +142 -1
  354. package/src/scripts/check_gate_reachability.ts +383 -0
  355. package/src/scripts/check_host_loadability.ts +104 -0
  356. package/src/scripts/check_loss_class_declared.ts +308 -0
  357. package/src/scripts/check_md_language.ts +15 -98
  358. package/src/scripts/check_memory_proposal.ts +18 -11
  359. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  360. package/src/scripts/check_no_external_sources.ts +281 -6
  361. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  362. package/src/scripts/check_pack_size.ts +59 -2
  363. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  364. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  365. package/src/scripts/check_publish_surface.ts +10 -1
  366. package/src/scripts/check_references.ts +24 -1
  367. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  368. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  369. package/src/scripts/check_score_contract.ts +26 -3
  370. package/src/scripts/check_static_parity.ts +285 -0
  371. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  372. package/src/scripts/check_suppression_hygiene.ts +15 -0
  373. package/src/scripts/ci_settle.ts +39 -2
  374. package/src/scripts/code_graph/build.ts +60 -3
  375. package/src/scripts/code_graph/extract.ts +44 -0
  376. package/src/scripts/code_graph/types.ts +24 -0
  377. package/src/scripts/collector_daemon.ts +714 -0
  378. package/src/scripts/config_cost_report.ts +302 -0
  379. package/src/scripts/consumer_matrix.ts +74 -1
  380. package/src/scripts/cost/budget.mjs +10 -3
  381. package/src/scripts/cost/track.mjs +10 -3
  382. package/src/scripts/council_cli.ts +37 -54
  383. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  384. package/src/scripts/evolution_lab.ts +980 -0
  385. package/src/scripts/external_sources_denylist.json +5 -18
  386. package/src/scripts/extract_audit_patterns.ts +21 -0
  387. package/src/scripts/fold_intake.ts +12 -1
  388. package/src/scripts/gen_discovery_baseline.ts +1 -1
  389. package/src/scripts/generate_capabilities_index.ts +12 -5
  390. package/src/scripts/generate_capability_matrix.ts +3 -3
  391. package/src/scripts/generate_command_flows.ts +2 -2
  392. package/src/scripts/generate_cookbook.ts +2 -2
  393. package/src/scripts/generate_index.ts +8 -1
  394. package/src/scripts/generate_knowledge_index.ts +2 -1
  395. package/src/scripts/generate_ownership_matrix.ts +2 -1
  396. package/src/scripts/generate_pack_manifests.ts +10 -2
  397. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  398. package/src/scripts/generate_settings_reference.ts +1 -1
  399. package/src/scripts/git_authorization_hook.ts +22 -1
  400. package/src/scripts/grade_target_readiness.ts +48 -5
  401. package/src/scripts/hook_effect_doctor.ts +261 -0
  402. package/src/scripts/hook_manifest.json +1 -1
  403. package/src/scripts/hook_manifest.yaml +98 -11
  404. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  405. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  406. package/src/scripts/hooks/concern_registry.ts +4 -0
  407. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  408. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  409. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  410. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  411. package/src/scripts/hooks/shims/install.sh +61 -0
  412. package/src/scripts/hooks/shims/php +101 -0
  413. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  414. package/src/scripts/hot_context_hook.ts +16 -0
  415. package/src/scripts/install-hooks.sh +20 -5
  416. package/src/scripts/install.ts +17 -35
  417. package/src/scripts/inventory_frontmatter.ts +2 -1
  418. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  419. package/src/scripts/lint_canonical_terms.ts +604 -0
  420. package/src/scripts/lint_composition_review.ts +619 -0
  421. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  422. package/src/scripts/lint_eval_specs.ts +593 -0
  423. package/src/scripts/lint_hook_manifest.ts +19 -0
  424. package/src/scripts/lint_host_portability.ts +373 -0
  425. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  426. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  427. package/src/scripts/lint_metric_consumers.ts +355 -0
  428. package/src/scripts/lint_skill_descriptions.ts +18 -1
  429. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  430. package/src/scripts/lint_skill_link_reach.ts +252 -0
  431. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  432. package/src/scripts/lint_ticket_buildable.ts +17 -1
  433. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  434. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  435. package/src/scripts/measure_docs_dead_links.ts +348 -0
  436. package/src/scripts/measure_host_capture.ts +461 -0
  437. package/src/scripts/migration_status.ts +3 -3
  438. package/src/scripts/model_rule_injection.ts +60 -0
  439. package/src/scripts/orchestration_record.ts +14 -0
  440. package/src/scripts/preamble_byte_census.ts +139 -10
  441. package/src/scripts/prepack-check.mjs +4 -1
  442. package/src/scripts/probe_turnaround.ts +384 -0
  443. package/src/scripts/probe_unblocked_ask.ts +279 -0
  444. package/src/scripts/render_benchmark_md.ts +1 -1
  445. package/src/scripts/rule_activation_census.ts +70 -9
  446. package/src/scripts/rule_backlinks.ts +1 -1
  447. package/src/scripts/run_lifecycle_suite.ts +208 -0
  448. package/src/scripts/run_skill_evals.ts +40 -0
  449. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  450. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  451. package/src/scripts/schemas/evals.schema.json +24 -1
  452. package/src/scripts/schemas/rule.schema.json +52 -1
  453. package/src/scripts/schemas/skill.schema.json +17 -2
  454. package/src/scripts/skill_overlap.ts +7 -1
  455. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  456. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  457. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  458. package/src/scripts/skill_usage_report.ts +2 -1
  459. package/src/scripts/stubs_due.ts +211 -0
  460. package/src/scripts/sweep_source_surfaces.ts +678 -0
  461. package/src/scripts/sync_pr_branch.ts +3 -3
  462. package/src/scripts/trigger_eval_grandfather.json +202 -222
  463. package/src/scripts/utilization_report.ts +22 -2
  464. package/src/server/schemas/settings.ts +5 -0
  465. package/src/templates/marketing-copy.yml +1 -1
  466. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -0,0 +1,81 @@
1
+ {
2
+ "_comment": "Pre-registered outcome bars for road-to-capability-native-execution, step 0.6. FIXED BEFORE ANY MEASUREMENT — the step requires the prereg commit to precede any default-preference change, so a bar edited after a run is a moved goalpost and must be recorded as one. Phase 3.4 binds the other direction: the published set must cover EVERY bar named here, with none missing and none present that this file does not name. Shape asserted by tests/scripts/capability_native_outcome_bars.test.ts — a bar with no falsifier FAILS the shape check rather than passing, which is the step's own verify clause. HONESTY ABOUT THE NUMBERS: three bars are DERIVED from a contract or a frozen-fixture property and say so; three are STATED DEFAULTS with a revisit-if, and say that instead of implying a derivation they do not have; one (evidence-completeness) is a contract restatement. A pre-registered threshold nobody can source is worse than none, because it looks measured.",
3
+ "schema_version": 1,
4
+ "registered_at": "2026-08-30",
5
+ "owner": "maintainer",
6
+ "review_by": "2027-02-28",
7
+ "roadmap": "road-to-capability-native-execution",
8
+ "step": "0.6",
9
+ "bars": [
10
+ {
11
+ "id": "dispatch-success",
12
+ "what": "Of the frozen 0.5 fixtures a dispatchable adapter advertises it can handle, the share it completes without an execution error.",
13
+ "threshold": 0.95,
14
+ "direction": "at-least",
15
+ "unit": "ratio",
16
+ "basis": "DERIVED, not chosen. 0.5 froze the fixture set and 2.4/3.5 require an advertised-but-undispatchable fixture to be REFUSED BEFORE EXECUTION — so a dispatch that reaches execution has already passed a dispatchability probe, and anything below near-total success means the probe is not doing its job. The bar is on the post-probe population, which is why it is high.",
17
+ "falsifier": "any dispatchable adapter completes fewer than 95% of the fixtures it advertised, measured on the frozen 0.5 set with its digest recorded",
18
+ "measured_by": "phase 3.2"
19
+ },
20
+ {
21
+ "id": "evidence-completeness",
22
+ "what": "Every field the evidence contract requires is present in the adapter's output for a completed run.",
23
+ "threshold": 1.0,
24
+ "direction": "at-least",
25
+ "unit": "ratio",
26
+ "basis": "DERIVED from the contract, not chosen: 3.2 requires each adapter to produce THE SAME required evidence contract on the same fixture. A required field is required; 0.99 would mean the contract is advisory, and a partial evidence envelope is the shape a reader mistakes for a complete one.",
27
+ "falsifier": "any completed run emits an envelope missing a field the contract marks required",
28
+ "measured_by": "phase 3.2"
29
+ },
30
+ {
31
+ "id": "token-context-cost",
32
+ "what": "Per-fixture token cost of the capability-dispatched arm against the direct-call arm.",
33
+ "threshold": 1.1,
34
+ "direction": "at-most",
35
+ "unit": "ratio-vs-baseline",
36
+ "basis": "STATED DEFAULT, not a measured optimum — said plainly rather than implying a derivation it does not have. 1.10 encodes 'the indirection may cost something, and not much'. Revisit-if: 3.3's first paired run lands outside 0.9-1.3 in either direction, which would mean the bar was set against the wrong order of magnitude rather than against a real regression.",
37
+ "falsifier": "the dispatched arm costs more than 1.10x the direct arm on the frozen fixtures, both figures reproducible from a command in the bench log",
38
+ "measured_by": "phase 3.3"
39
+ },
40
+ {
41
+ "id": "wall-clock",
42
+ "what": "Per-fixture wall-clock of the capability-dispatched arm against the direct-call arm.",
43
+ "threshold": 1.25,
44
+ "direction": "at-most",
45
+ "unit": "ratio-vs-baseline",
46
+ "basis": "STATED DEFAULT. Looser than the token bar on purpose: dispatch adds a probe and a selection step whose cost is wall-clock rather than tokens, so a bar equal to the token one would fail on the mechanism working as designed. Revisit-if: the probe's own measured cost exceeds a quarter of the baseline, at which point the bar is measuring the probe rather than the dispatch.",
47
+ "falsifier": "median wall-clock of the dispatched arm exceeds 1.25x the direct arm over the frozen fixtures",
48
+ "measured_by": "phase 3.3"
49
+ },
50
+ {
51
+ "id": "setup-friction",
52
+ "what": "Manual steps a first-time operator performs before a dispatchable adapter runs at all.",
53
+ "threshold": 2,
54
+ "direction": "at-most",
55
+ "unit": "manual-steps",
56
+ "basis": "STATED DEFAULT, and the unit is the argument: steps are counted, not timed, because a timing figure on one machine is not transferable and a step count is. Two is 'install the engine, point at it'. Revisit-if: any adapter needs a credential, at which point the honest count is three and the bar moves with the reason recorded rather than the adapter being excluded.",
57
+ "falsifier": "any adapter counted as dispatchable needs more than two manual steps from a clean machine, counted from its own documented setup",
58
+ "measured_by": "phase 3.2"
59
+ },
60
+ {
61
+ "id": "deterministic-replay",
62
+ "what": "Re-running one fixture through one adapter twice yields the same required evidence fields.",
63
+ "threshold": 1.0,
64
+ "direction": "at-least",
65
+ "unit": "ratio",
66
+ "basis": "DERIVED. The frozen fixtures exist so a result is reproducible; an adapter whose required fields vary between runs cannot be compared against another adapter at all, which is what 3.2 exists to do. Timestamps and durations are explicitly OUT of the compared set — a bar that failed on a clock would be measuring the clock.",
67
+ "falsifier": "two runs of one fixture through one adapter differ in any required evidence field outside the declared volatile set",
68
+ "measured_by": "phase 3.2"
69
+ },
70
+ {
71
+ "id": "degraded-run-honesty",
72
+ "what": "A run that could not complete the full contract reports the degradation rather than emitting a partial envelope as if complete.",
73
+ "threshold": 1.0,
74
+ "direction": "at-least",
75
+ "unit": "ratio",
76
+ "basis": "DERIVED, and it is the bar the others rest on. Every ratio above is computed over runs the adapter CLAIMS completed; a degraded run silently counted as complete inflates all six. This is the same soundness invariant road-to-governed-harness-evolution 1.2 states for its activation ladder — an unobserved state is never silently converted to success.",
77
+ "falsifier": "any degraded run emits an envelope that a consumer cannot distinguish from a complete one",
78
+ "measured_by": "phase 3.2, phase 3.4"
79
+ }
80
+ ]
81
+ }
@@ -124,6 +124,41 @@ ci_only:
124
124
  - id: report_pack_delta
125
125
  class: artifact
126
126
  reason: "a pull-request-only delta report with no local meaning (base==head reads +0.0 KB and the step writes nothing); it packs two refs in throwaway worktrees at ~1 min, cannot red the build, and is reachable on demand via `task report-pack-delta`"
127
+
128
+ # road-to-supervised-telemetry-collector step 4.2 (AC-7). Runs the
129
+ # dispatcher-reaching suite TWICE — once with the collector present-but-off,
130
+ # once with it aliased away entirely — and compares per-test verdicts rather
131
+ # than declaring each run green. That is the whole set twice, roughly a minute,
132
+ # which is not a per-change local gate; and its result is a property of a
133
+ # clean checkout rather than of a developer's working tree, since it pins
134
+ # HOME to an empty directory precisely so the invoking user's own collector
135
+ # state cannot decide the answer.
136
+ #
137
+ # Reachable on demand: `./scripts-run src/scripts/check_static_parity`.
138
+ - id: check_static_parity
139
+ class: benchmark
140
+ reason: "two full runs of the dispatcher-reaching suite, compared per-test verdict by verdict, ~1 minute; a per-change local gate cannot afford it and its answer is a property of a clean checkout rather than of a working tree"
141
+ # road-to-supervised-telemetry-collector step 5.2. What is CI-only is this
142
+ # WRAPPER, whose whole job is to write
143
+ # `internal/reports/supervision-lifecycle.json` stamped with
144
+ # `git rev-parse HEAD`. That artifact is gitignored and read by
145
+ # `check_supervision_claim_atomicity`, which refuses any result whose recorded
146
+ # revision is not HEAD — so an artifact written during a local run of a dirty
147
+ # working tree is evidence about a revision nobody shipped.
148
+ #
149
+ # CORRECTED on R2 round-3 finding 7. This note used to say the five properties
150
+ # "run in the ordinary vitest chain" locally AND that a `task ci` wrapper
151
+ # "would spawn real daemons on every local run" — which cannot both be true,
152
+ # and the second half was already stale: the same change excluded
153
+ # `collector_lifecycle.test.ts` from the `node-tests` shards. The accurate
154
+ # position is that the suite runs on demand and in the dedicated
155
+ # `Collector Lifecycle` job, and the wrapper's CI-only status rests on the
156
+ # revision-stamped artifact alone — the argument that survives.
157
+ #
158
+ # Reachable on demand: `./scripts-run src/scripts/run_lifecycle_suite`.
159
+ - id: run_lifecycle_suite
160
+ class: artifact
161
+ reason: "writes the revision-stamped lifecycle evidence artifact the atomicity gate reads; the artifact is gitignored and only meaningful at the revision CI is testing, while the five properties themselves already run locally in tests/scripts/collector_lifecycle.test.ts"
127
162
  - id: classify_change_risk
128
163
  class: benchmark
129
164
  reason: "invoked as the nightly drift workflow's self-test step; the classifier itself gates nothing and its `--self-test` is runnable locally on demand (`./scripts-run src/scripts/classify_change_risk --self-test`)"
@@ -139,6 +174,27 @@ ci_only:
139
174
  - id: check_finding_dispositions
140
175
  class: release
141
176
  reason: "adjudicates the release-PR self-review findings ledger, whose input JSON is produced by the self-review workflow job"
177
+ # road-to-source-silence Phase 5.3. Two modes, and the distinction is the whole
178
+ # reason this is a declaration rather than a `task ci` entry.
179
+ #
180
+ # The mode a CI workflow invokes on a schedule is the FIVE-SURFACE CENSUS
181
+ # (source-surface-sweep.yml, weekly). It needs `gh` for the pull-request
182
+ # surface and a full-depth clone for the 9,000-commit trunk surface, it takes
183
+ # minutes, it writes no verdict, and it deliberately CANNOT red the build — a
184
+ # scheduled job that fails `main` for a residual count nobody can lower this
185
+ # week is a job that gets disabled. Putting it in `task ci` would add minutes
186
+ # to every local run for a number that is a standing observation, not a gate.
187
+ #
188
+ # The mode that IS a gate — `--gate-metadata`, which refuses source
189
+ # attribution in a branch name, PR title, PR body or commit message — has a
190
+ # stronger local story than `task ci` membership gives anything else here: it
191
+ # runs on PRE-PUSH via src/scripts/hooks/prepush_metadata_sources.sh, i.e.
192
+ # BEFORE the metadata is public, which is the only moment fixing it is free.
193
+ # A contributor therefore discovers that failure locally by construction,
194
+ # which is exactly the harm this checker exists to prevent.
195
+ - id: sweep_source_surfaces
196
+ class: network
197
+ reason: "the CI invocation is the weekly five-surface census — needs `gh` for the PR surface and a full-depth clone for the ~9,000-commit trunk surface, writes counts not a verdict, and is deliberately non-failing; its GATE mode (`--gate-metadata`) is reachable locally on pre-push via src/scripts/hooks/prepush_metadata_sources.sh and by hand, so no failure is discoverable only after a push"
142
198
  - id: rule_trigger_eval
143
199
  class: network
144
200
  reason: "live cross-model LLM trigger evaluation in the secret-gated canary workflow; advisory, paid, and never gating"
@@ -213,6 +269,30 @@ ci_only:
213
269
  # worth remote enforcement, OR it should simply be added to a workflow. Prefer
214
270
  # adding it: a local-only gate is the direction that let real defects merge.
215
271
  local_only:
272
+ - id: check_host_loadability_reach
273
+ class: developer-machine-scoped
274
+ reason: >
275
+ `check_host_loadability --reach` asks whether each generated host tree
276
+ carries artefacts, and — when it does not — whether the TOOL is absent or
277
+ the PROJECTION is dead. Those two are opposite findings that every current
278
+ gate reports as the same green, because a checker that returns early on a
279
+ missing tree cannot tell them apart.
280
+
281
+ Local-only by declaration rather than by omission, and the reason inverts
282
+ the obvious one: the verdict depends on which host tools are INSTALLED,
283
+ and a CI runner has none. Wired into a workflow, every row would resolve
284
+ `skipped-tool-absent` and the gate would scan nothing — the empty-scope
285
+ false green this repository's gate-coverage manifest exists to refuse.
286
+
287
+ This CORRECTS `road-to-skill-ecosystem-runtime-enforcement` Phase 3 Step 2,
288
+ which asked for a continuous-integration-only job. That instruction fits
289
+ the SHAPE half (`check_host_loadability --root .`), which is already
290
+ wired into `consistency.yml` and does not depend on installed tools; it
291
+ does not fit the reach half, and wiring it there would have produced a
292
+ permanently-skipping check that looked like coverage. Measured on a
293
+ developer machine: 6 of 6 host surfaces present and projecting
294
+ (claude-code 13, cursor 228, cline 14, windsurf 215, gemini-cli 1,
295
+ copilot 1).
216
296
  - id: check_hook_bundle_content
217
297
  class: developer-machine-scoped
218
298
  reason: >
@@ -0,0 +1,43 @@
1
+ # Drafting channel registry — the `--channel` enum and its per-channel
2
+ # defaults, extracted from docs/contracts/write-engine.md § Per-channel
3
+ # defaults (road-to-channel-contract-and-profile-drift Phase 1.2).
4
+ #
5
+ # WHY THIS IS A SIBLING OF reach-channels.yml AND NOT AN EXTENSION OF IT.
6
+ # One line, as the step requires: a drafting channel is an OUTPUT SHAPE for
7
+ # prose this package writes (how long, how many paragraphs, whether hashtags
8
+ # are allowed), whereas a reach channel is an EXTERNAL RETRIEVAL BACKEND the
9
+ # operator installs and the package never calls — that file's own header says
10
+ # it is "not a routing table, not a recommendation, not an agent-facing
11
+ # surface" and that its Phase-0 benchmark returned `band: stop`, so nothing in
12
+ # it is agent-facing at all. The two share the word "channel" and no field: a
13
+ # drafting channel has no backend, no install string, no health probe and no
14
+ # lifecycle; a reach channel has no length and no cadence. Merging them would
15
+ # produce one schema in which every field is optional for half its rows, which
16
+ # is the "two truths for one word" this roadmap's Risk Register row 2 names.
17
+ #
18
+ # WHAT READS THIS FILE. `docs/contracts/write-engine.md` is the prose contract
19
+ # and stays the human-facing statement of the same values; this file is the
20
+ # machine-checked copy, and
21
+ # `tests/scripts/drafting_channels_schema.test.ts` asserts the two agree, so a
22
+ # future edit to one that is not made to the other fails rather than drifts.
23
+ #
24
+ # THE VALUE IS THE FLAG VALUE. `id` is what a user types after `--channel=`.
25
+ # `linkedin-post` is the value; `linkedin` is not a value and is rejected —
26
+ # see the test case that pins exactly that, because the short form is the
27
+ # plausible typo and silently accepting it would make the enum decorative.
28
+ schema_version: drafting-channels-v1
29
+ channels:
30
+ - id: tweet
31
+ length_default: 50
32
+ cadence: One paragraph, no lists.
33
+ - id: linkedin-post
34
+ length_default: 180
35
+ cadence: >-
36
+ 2–4 short paragraphs. Hashtags only if
37
+ `style.fingerprint.hashtag_rules` allows.
38
+ - id: blog
39
+ length_default: 600
40
+ cadence: Inherits `style.fingerprint.paragraph_cadence`.
41
+ - id: freeform
42
+ length_default: 250
43
+ cadence: Inherits `style.fingerprint.paragraph_cadence`.
@@ -1,38 +1,40 @@
1
1
  {
2
- "_comment": "Roadmap-estate ratchet (road-to-estate-drawdown T2 + T3). POLICY ONLY \u2014 this file no longer stores a number. Until ADR-243 it carried a measured `baseline` object plus a `baseline_history` audit trail (113 entries at removal, last measurement 23/59/60), and that made it the most-conflicted non-generated path in the repository: 7 of 7 CONFLICTING open PRs on 2026-08-21, and 39 of 43 non-merge commits in a 60-day window moving the baseline. `check_estate_count` now MEASURES the floor on the base ref's own tree with the same functions it measures HEAD with, so the 'before' side is still something the change under review cannot rewrite \u2014 it is just no longer something a human has to remember to walk. Two failure classes went with the storage and are now unrepresentable: a baseline left above the truth (spendable headroom, which the gate used to fail on as an un-walked tightening), and a baseline left below it after main archived a roadmap without walking the number, which reddened every branch that merged main. The legitimate-growth path the stored number provided \u2014 a raise carrying a recorded reason \u2014 is replaced by `estate_growth_exempt: <reason>` in the frontmatter of a roadmap the change touches, read from the diff so it cannot be banked. T1's proposed ceilings stay under `target` and are still NOT registered: they are the maintainer's to set.",
3
- "schema_version": 2,
4
- "registered_at": "2026-08-18",
5
- "baseline_removed_at": "2026-08-22",
6
- "owner": "maintainer",
7
- "review_by": "2027-08-18",
8
- "metric": {
9
- "basis": "src/scripts/check_estate_count.ts. The live side uses collect() from update_roadmap_progress \u2014 the same parser the dashboard is generated from, imported rather than re-implemented. The floor side runs the SAME functions over a scratch copy of the base ref's agents/roadmaps/, materialised by _lib/base_tree.ts (git ls-tree + git cat-file --batch; `git archive` cannot be used here because .gitattributes carries `/agents export-ignore` and would yield an empty, silently-zero tree). SKILL METRICS (added 2026-08-24): _lib/skill_estate.ts walks src/skills/*/SKILL.md under the SAME root, so the floor side measures the base ref's own skill tree with the same function. That needs a SECOND materialised subtree \u2014 materialiseSubtree takes one prefix \u2014 and the two are independent on purpose: a base ref with no src/skills (an old tag, a shallow clone) drops the skill metrics and leaves the roadmap metrics ratcheting.",
10
- "active_roadmaps": "non-draft roadmap candidates at the top level of agents/roadmaps/, as collect() counts them. This is exactly the number the dashboard header prints as 'N open roadmaps'.",
11
- "later_roadmaps": "roadmap-shaped *.md files under agents/roadmaps/later/ \u2014 the same is_roadmap_candidate name filter the active side uses, so later/README.md is not counted. Counted from the filesystem because parked roadmaps sit outside collect()'s corpus by design; they are estate all the same, and a drawdown that moved everything into later/ and called the number down would be the burial T1's quality anchor exists to prevent.",
12
- "open_blockers": "blockers whose Status does not start with `resolved`, summed over the active and later corpora.",
13
- "floor": "the same three metrics measured at the base ref (origin/main, else the merge commit's first parent). No base ref resolves -> no floor -> the gate FAILS rather than skipping: a shrink-only gate with no floor passes every possible tree. `--base <ref>` is the explicit escape.",
14
- "skill_count": "Maintained src/skills/*/SKILL.md files; `lifecycle: deprecated` EXCLUDED. The exclusion is load-bearing rather than tidy: with deprecated skills counted, deprecating one would create no headroom and the retirement mechanism would be unusable against its own gate. 0 skills carry it today, so the exclusion is a no-op now and a correctness property once a tranche lands. Measured 2026-08-24: 299. Reproduce with `find src/skills -name SKILL.md | wc -l` (299 including any deprecated) or `npx tsx -e \"import {measureSkillEstate} from './src/scripts/_lib/skill_estate.ts'; console.log(measureSkillEstate(process.cwd()))\"` for the split.",
15
- "skill_description_tokens": "Exact-BPE tokens (js-tiktoken, cl100k_base, via _lib/token_count.ts gpt_tokens) across those skills' `description:` frontmatter fields ONLY \u2014 not bodies. Measured 2026-08-24: 11,461 over 299 skills (52,983 chars). A SECOND DIMENSION, not a companion figure: a count ratchet alone is gameable by merging four large skills into one file, which lowers the count while the description payload a host must carry stays put. AI council 2/2 (2026-08-24) asked for both in one gate over the roadmap's own recommendation of count-plus-informational-figure. UNRESOLVED rather than approximated: when the tokeniser does not resolve on either side the metric is dropped from the compare with a printed reason, because an exact reading against a proxy one differs by more than the growth this gate is trying to catch.",
16
- "skill_metric_rejected_candidates": "Measured before choosing, not argued. (b) catalogue bytes via _lib/skill_catalogue.ts read 0 on a real checkout: readProjectedCatalogue walks .claude/skills, empty in any tree where `task generate-tools` cannot complete (it fails under projection.mode=scoped without the config package) \u2014 a ratchet whose reading depends on whether a generator ran reds for the environment. (d) host-listing slots are the host's decision, not the repository's: a measured install published its own budget event stating it had stripped every description and dropped 402 entries. Neither is reproducible from the repo, so neither can carry a floor."
17
- },
18
- "growth_allowances": {
19
- "_comment": "An exact floor leaves no incidental headroom, so every legitimate increase needs a named path. Two are automatic because existing policy already sanctions the act; the third is the general authorisation.",
20
- "active_roadmaps": "+1 per addition carrying `estate_offset_exempt: <reason>` in its own frontmatter (unchanged T3 key). Without this the sanctioned un-offsettable addition would fail the count half with no green path.",
21
- "later_roadmaps": "+1 per roadmap moved from the active top level into later/ in the same change. Parking relocates estate rather than creating it. It does NOT cover a later/ file that appears from nowhere, and it is keyed on parking rather than on any offset so that an archive move cannot buy a new later/ file.",
22
- "open_blockers": "none. Nothing in the policy sanctions a new blocker, so it takes the claim path or nothing.",
23
- "claim": "`estate_growth_exempt: <reason>` added, in this change, to the frontmatter of any roadmap under agents/roadmaps/. Authorises growth in any metric, with the reason printed. Diff-scoped, so a claim left in a file authorises nothing later \u2014 the banking failure a stored baseline had. Deliberately unbounded, which a stored baseline could not afford: there the surplus of an over-raise was inherited by the next change, where nobody could act on it; here the next change's floor IS this change's measurement, so there is no surplus to inherit.",
24
- "skill_count": "0 \u2014 no allowance, deliberately. The defect this metric addresses is a corpus that grew +8 in one release (290 at 14.0.0, 291 at 14.9.0 and 14.10.0, 299 at 14.11.0) with nothing objecting. An addition takes the estate_growth_exempt claim path \u2014 a recorded reason read from the diff \u2014 or it fails.",
25
- "skill_description_tokens": "0 \u2014 same reasoning. An addition that grows the description payload without adding a file is the gaming path this dimension exists to close, and an allowance would reopen it."
26
- },
27
- "target": {
28
- "_comment": "T1's proposed ceilings, kept as the destination. PROPOSALS, NOT REGISTERED: the roadmap says in as many words that both numbers and the window belong to the maintainer, and no date is pinned in this file. Nothing reads these values \u2014 `one_in_one_out.applies_above_active` is the only threshold the gate evaluates.",
29
- "active_roadmaps": 15,
30
- "open_blockers": 12,
31
- "window": "roughly six weeks from campaign start (drafted; unregistered)"
32
- },
33
- "one_in_one_out": {
34
- "_comment": "T3. `applies_above_active: null` means UNCONDITIONAL. T3 phrases the condition as 'while the active count sits above target', and T1 says the target belongs to the maintainer \u2014 so rather than inventing a ceiling so the condition could be evaluated, null states that no ceiling is registered and the lint therefore applies. Registering a number here is how it gets a threshold; registering one above the live count is how it is turned off.",
35
- "applies_above_active": null,
36
- "exemption": "estate_offset_exempt: <reason> in the added roadmap's own frontmatter. The key lives in the file rather than in this config for the reason RATCHET_RESET_KEY gives for living inside its baseline JSON: the claim shows up in the diff of the change that makes it."
37
- }
2
+ "_comment": "Roadmap-estate ratchet (road-to-estate-drawdown T2 + T3). POLICY ONLY — this file no longer stores a number. Until ADR-243 it carried a measured `baseline` object plus a `baseline_history` audit trail (113 entries at removal, last measurement 23/59/60), and that made it the most-conflicted non-generated path in the repository: 7 of 7 CONFLICTING open PRs on 2026-08-21, and 39 of 43 non-merge commits in a 60-day window moving the baseline. `check_estate_count` now MEASURES the floor on the base ref's own tree with the same functions it measures HEAD with, so the 'before' side is still something the change under review cannot rewrite — it is just no longer something a human has to remember to walk. Two failure classes went with the storage and are now unrepresentable: a baseline left above the truth (spendable headroom, which the gate used to fail on as an un-walked tightening), and a baseline left below it after main archived a roadmap without walking the number, which reddened every branch that merged main. The legitimate-growth path the stored number provided — a raise carrying a recorded reason — is replaced by `estate_growth_exempt: <reason>` in the frontmatter of a roadmap the change touches, read from the diff so it cannot be banked. T1's proposed ceilings stay under `target` and are still NOT registered: they are the maintainer's to set.",
3
+ "schema_version": 2,
4
+ "registered_at": "2026-08-18",
5
+ "baseline_removed_at": "2026-08-22",
6
+ "owner": "maintainer",
7
+ "review_by": "2027-08-18",
8
+ "metric": {
9
+ "basis": "src/scripts/check_estate_count.ts. The live side uses collect() from update_roadmap_progress — the same parser the dashboard is generated from, imported rather than re-implemented. The floor side runs the SAME functions over a scratch copy of the base ref's agents/roadmaps/, materialised by _lib/base_tree.ts (git ls-tree + git cat-file --batch; `git archive` cannot be used here because .gitattributes carries `/agents export-ignore` and would yield an empty, silently-zero tree). SKILL METRICS (added 2026-08-24): _lib/skill_estate.ts walks src/skills/*/SKILL.md under the SAME root, so the floor side measures the base ref's own skill tree with the same function. That needs a SECOND materialised subtree — materialiseSubtree takes one prefix — and the two are independent on purpose: a base ref with no src/skills (an old tag, a shallow clone) drops the skill metrics and leaves the roadmap metrics ratcheting.",
10
+ "active_roadmaps": "non-draft roadmap candidates at the top level of agents/roadmaps/, as collect() counts them. This is exactly the number the dashboard header prints as 'N open roadmaps'.",
11
+ "later_roadmaps": "roadmap-shaped *.md files under agents/roadmaps/later/ — the same is_roadmap_candidate name filter the active side uses, so later/README.md is not counted. Counted from the filesystem because parked roadmaps sit outside collect()'s corpus by design; they are estate all the same, and a drawdown that moved everything into later/ and called the number down would be the burial T1's quality anchor exists to prevent.",
12
+ "open_blockers": "blockers whose Status does not start with `resolved`, summed over the active and later corpora.",
13
+ "floor": "the same three metrics measured at the base ref (origin/main, else the merge commit's first parent). No base ref resolves -> no floor -> the gate FAILS rather than skipping: a shrink-only gate with no floor passes every possible tree. `--base <ref>` is the explicit escape.",
14
+ "skill_count": "Maintained src/skills/*/SKILL.md files; `lifecycle: deprecated` EXCLUDED. The exclusion is load-bearing rather than tidy: with deprecated skills counted, deprecating one would create no headroom and the retirement mechanism would be unusable against its own gate. 0 skills carry it today, so the exclusion is a no-op now and a correctness property once a tranche lands. Measured 2026-08-24: 299. Reproduce with `find src/skills -name SKILL.md | wc -l` (299 including any deprecated) or `npx tsx -e \"import {measureSkillEstate} from './src/scripts/_lib/skill_estate.ts'; console.log(measureSkillEstate(process.cwd()))\"` for the split.",
15
+ "skill_description_tokens": "Exact-BPE tokens (js-tiktoken, cl100k_base, via _lib/token_count.ts gpt_tokens) across those skills' `description:` frontmatter fields ONLY — not bodies. Measured 2026-08-24: 11,461 over 299 skills (52,983 chars). A SECOND DIMENSION, not a companion figure: a count ratchet alone is gameable by merging four large skills into one file, which lowers the count while the description payload a host must carry stays put. AI council 2/2 (2026-08-24) asked for both in one gate over the roadmap's own recommendation of count-plus-informational-figure. UNRESOLVED rather than approximated: when the tokeniser does not resolve on either side the metric is dropped from the compare with a printed reason, because an exact reading against a proxy one differs by more than the growth this gate is trying to catch.",
16
+ "skill_metric_rejected_candidates": "Measured before choosing, not argued. (b) catalogue bytes via _lib/skill_catalogue.ts read 0 on a real checkout: readProjectedCatalogue walks .claude/skills, empty in any tree where `task generate-tools` cannot complete (it fails under projection.mode=scoped without the config package) — a ratchet whose reading depends on whether a generator ran reds for the environment. (d) host-listing slots are the host's decision, not the repository's: a measured install published its own budget event stating it had stripped every description and dropped 402 entries. Neither is reproducible from the repo, so neither can carry a floor.",
17
+ "concern_count": "Hook concerns declared under the `concerns:` map in src/scripts/hook_manifest.yaml. Measured 2026-08-30: 55. Reproduce with `npx tsx -e \"import {countConcerns} from './src/scripts/_lib/concern_estate.ts';import fs from 'node:fs';console.log(countConcerns(fs.readFileSync('src/scripts/hook_manifest.yaml','utf-8')))\"`. THE ORIGINATING ROADMAP'S REPRODUCE COMMAND IS A PROXY AND OVER-COUNTS, and the correction is recorded here rather than only in the roadmap because this file is what a later reader checks the number against. `grep -cE '^ [a-z][a-z0-9_-]*:$'` greps the WHOLE manifest, so it also counts members of `roles:`, `platforms:` and `native_event_aliases:`, which sit at the same two-space indent. Re-measured at the roadmap's own six pins the over-count is EXACTLY 16 every time: 63/65/65/68/69/71 by the grep is 47/49/49/52/53/55 scoped. Both consequences, because they point in opposite directions -- the FINDING survives untouched (the delta is constant, so the axis climbs +8 either way and is growing exactly as the roadmap says), and the ABSOLUTE FIGURE does not (the axis stands at 55, and a floor of 71 is one this gate's own parser could never reproduce, i.e. a gate that fails on its first honest run). REJECTED CANDIDATES, measured rather than argued: counting `platforms:` rows instead -- rejected, it is 8 and flat across all six pins, so it measures host coverage and not concern growth; counting the per-(platform,event) cap in lint_hook_concern_budget.ts -- rejected, DEFAULT_MAX_PER_EVENT=8 is blind to total growth by construction (eight new concerns spread across eight events violate nothing) and it ships DEFAULT_HARD_FAIL=false, which is why this axis needed a ratchet at all."
18
+ },
19
+ "growth_allowances": {
20
+ "_comment": "An exact floor leaves no incidental headroom, so every legitimate increase needs a named path. Two are automatic because existing policy already sanctions the act; the third is the general authorisation.",
21
+ "active_roadmaps": "+1 per addition carrying `estate_offset_exempt: <reason>` in its own frontmatter (unchanged T3 key). Without this the sanctioned un-offsettable addition would fail the count half with no green path.",
22
+ "later_roadmaps": "+1 per roadmap moved from the active top level into later/ in the same change. Parking relocates estate rather than creating it. It does NOT cover a later/ file that appears from nowhere, and it is keyed on parking rather than on any offset so that an archive move cannot buy a new later/ file.",
23
+ "open_blockers": "none. Nothing in the policy sanctions a new blocker, so it takes the claim path or nothing.",
24
+ "claim": "`estate_growth_exempt: <reason>` added, in this change, to the frontmatter of any roadmap under agents/roadmaps/. Authorises growth in any metric, with the reason printed. Diff-scoped, so a claim left in a file authorises nothing later — the banking failure a stored baseline had. Deliberately unbounded, which a stored baseline could not afford: there the surplus of an over-raise was inherited by the next change, where nobody could act on it; here the next change's floor IS this change's measurement, so there is no surplus to inherit.",
25
+ "skill_count": "0 — no allowance, deliberately. The defect this metric addresses is a corpus that grew +8 in one release (290 at 14.0.0, 291 at 14.9.0 and 14.10.0, 299 at 14.11.0) with nothing objecting. An addition takes the estate_growth_exempt claim path — a recorded reason read from the diff — or it fails.",
26
+ "skill_description_tokens": "0 — same reasoning. An addition that grows the description payload without adding a file is the gaming path this dimension exists to close, and an allowance would reopen it.",
27
+ "concern_count": "0 — no allowance, deliberately, and the same reason skill_count gives. An allowance reopens the gaming path the dimension exists to close. Sharper here than for skills: eight concerns spread across eight events violate the existing per-event cap zero times, which is precisely why a total-growth ratchet was needed and precisely why it must not carry a per-change freebie. An addition takes the estate_growth_exempt claim path — a recorded reason read from the diff — or it fails."
28
+ },
29
+ "target": {
30
+ "_comment": "T1's proposed ceilings, kept as the destination. PROPOSALS, NOT REGISTERED: the roadmap says in as many words that both numbers and the window belong to the maintainer, and no date is pinned in this file. Nothing reads these values — `one_in_one_out.applies_above_active` is the only threshold the gate evaluates.",
31
+ "active_roadmaps": 15,
32
+ "open_blockers": 12,
33
+ "window": "roughly six weeks from campaign start (drafted; unregistered)"
34
+ },
35
+ "one_in_one_out": {
36
+ "_comment": "T3. `applies_above_active: null` means UNCONDITIONAL. T3 phrases the condition as 'while the active count sits above target', and T1 says the target belongs to the maintainer — so rather than inventing a ceiling so the condition could be evaluated, null states that no ceiling is registered and the lint therefore applies. Registering a number here is how it gets a threshold; registering one above the live count is how it is turned off.",
37
+ "applies_above_active": null,
38
+ "exemption": "estate_offset_exempt: <reason> in the added roadmap's own frontmatter. The key lives in the file rather than in this config for the reason RATCHET_RESET_KEY gives for living inside its baseline JSON: the claim shows up in the diff of the change that makes it."
39
+ }
38
40
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "_comment": "Outside-in evaluator budgets (road-to-credible-install Phase 6). VALUES ARE FROZEN FROM MEASURED ACCEPTANCE NUMBERS of Phases 0-3 (2026-07-27, packed tarball @ 9.8.0 tree, --omit=dev consumer install), never invented. The umbrella harness (src/scripts/evaluator_umbrella.sh) measures the packed artifact and check_evaluator_budgets.ts enforces: absolute budget AND >regression_pct growth vs last_measured fails even under budget. Owner + review date are lint-enforced (lint_budget_ownership). Timing metrics carry a per-entry regression_pct override (200) \u2014 wall-clock noise would flap a 10% creep rule; their absolute max is the binding gate. Sizes/counts keep the tight 10% creep.",
2
+ "_comment": "Outside-in evaluator budgets (road-to-credible-install Phase 6). VALUES ARE FROZEN FROM MEASURED ACCEPTANCE NUMBERS of Phases 0-3 (2026-07-27, packed tarball @ 9.8.0 tree, --omit=dev consumer install), never invented. The umbrella harness (src/scripts/evaluator_umbrella.sh) measures the packed artifact and check_evaluator_budgets.ts enforces: absolute budget AND >regression_pct growth vs last_measured fails even under budget. Owner + review date are lint-enforced (lint_budget_ownership). Timing metrics carry a per-entry regression_pct override (200) — wall-clock noise would flap a 10% creep rule; their absolute max is the binding gate. Sizes/counts keep the tight 10% creep.",
3
3
  "schema_version": 1,
4
4
  "owner": "maintainer",
5
5
  "review_by": "2027-07-27",
@@ -11,23 +11,23 @@
11
11
  "always_blocking": [
12
12
  "a metric with no measurement supplied"
13
13
  ],
14
- "rationale": "road-to-gates-that-can-fail Phase 5. A hard fail on main turns every legitimate command addition into a blocked merge, which is how budgets get quietly raised with a cushion instead of consciously \u2014 so budget / regression / drift findings are ADVISORY on main, the nightly and ordinary PRs, and BLOCKING on a release ref. Not a weakening: before the Phase-4 path triggers, this gate ran on release PRs and the nightly only, so the surfaces that now warn never saw it at all. A LOCAL run (no CI env) is strict, because a maintainer running it by hand \u2014 including release.ts \u2014 wants the strict answer and blocks nobody. A metric with NO measurement is always blocking in either posture: that is a broken harness reporting green on nothing. Implemented in src/scripts/check_evaluator_budgets.ts::detectPosture; override with --posture warn|fail.",
15
- "delivery": "This posture IS the nightly-visibility route (council 2026-08-02, blocker nightly-visibility-owner), not a second mechanism beside it: the nightly publishes measurement_record below, a later run re-measures and compares, and the contradiction warns on main / fails on release. No notification channel, no auto-managed issue \u2014 a one-maintainer channel producing routine noise gets muted, and a muted channel reproduces the original failure."
14
+ "rationale": "road-to-gates-that-can-fail Phase 5. A hard fail on main turns every legitimate command addition into a blocked merge, which is how budgets get quietly raised with a cushion instead of consciously — so budget / regression / drift findings are ADVISORY on main, the nightly and ordinary PRs, and BLOCKING on a release ref. Not a weakening: before the Phase-4 path triggers, this gate ran on release PRs and the nightly only, so the surfaces that now warn never saw it at all. A LOCAL run (no CI env) is strict, because a maintainer running it by hand — including release.ts — wants the strict answer and blocks nobody. A metric with NO measurement is always blocking in either posture: that is a broken harness reporting green on nothing. Implemented in src/scripts/check_evaluator_budgets.ts::detectPosture; override with --posture warn|fail.",
15
+ "delivery": "This posture IS the nightly-visibility route (council 2026-08-02, blocker nightly-visibility-owner), not a second mechanism beside it: the nightly publishes measurement_record below, a later run re-measures and compares, and the contradiction warns on main / fails on release. No notification channel, no auto-managed issue — a one-maintainer channel producing routine noise gets muted, and a muted channel reproduces the original failure."
16
16
  },
17
17
  "measurement_record": {
18
18
  "path": "agents/evidence/metrics/evaluator-measurements.json",
19
- "written_by": "src/scripts/evaluator_umbrella.sh (UMBRELLA_RECORD=1 \u2014 the nightly sets it)",
19
+ "written_by": "src/scripts/evaluator_umbrella.sh (UMBRELLA_RECORD=1 — the nightly sets it)",
20
20
  "compared_by": "src/scripts/check_evaluator_budgets.ts --recorded",
21
21
  "note": "Only entries WITHOUT `deterministic: false` participate in the drift comparison. The council's recorded objection was that a non-deterministic comparison produces noise and gets ignored; determinism is therefore a precondition, verified per metric, not an assumption."
22
22
  },
23
23
  "remeasurement_2026_08_02": {
24
24
  "verified_against_a_fresh_run": {
25
- "cli_help_command_count": "80 \u2014 three consecutive runs of the pinned method on an unchanged tree returned 80/80/80. Matches last_measured; deterministic confirmed.",
26
- "mcp_public_tool_count": "19 \u2014 two consecutive tools/list runs on a freshly built dist/mcp/server.mjs returned 19/19. Matches last_measured; deterministic confirmed."
25
+ "cli_help_command_count": "80 — three consecutive runs of the pinned method on an unchanged tree returned 80/80/80. Matches last_measured; deterministic confirmed.",
26
+ "mcp_public_tool_count": "19 — two consecutive tools/list runs on a freshly built dist/mcp/server.mjs returned 19/19. Matches last_measured; deterministic confirmed."
27
27
  },
28
- "not_re_measured": "unpacked_size_mb, node_modules_mb, runtime_dep_count, cli_version_cold_ms, mcp_boot_to_initialize_ms. All five require the packed-tarball harness (npm pack of a fully built tree, then a clean `npm install --omit=dev <tarball>` into a scratch project) that evaluator_umbrella.sh runs in CI. They were NOT re-measured in this pass and their values remain the 2026-07-27 acceptance numbers \u2014 stated rather than invented. The next nightly writes the real numbers into measurement_record, and the drift check then reports any contradiction with last_measured on the PR that carries it."
28
+ "not_re_measured": "unpacked_size_mb, node_modules_mb, runtime_dep_count, cli_version_cold_ms, mcp_boot_to_initialize_ms. All five require the packed-tarball harness (npm pack of a fully built tree, then a clean `npm install --omit=dev <tarball>` into a scratch project) that evaluator_umbrella.sh runs in CI. They were NOT re-measured in this pass and their values remain the 2026-07-27 acceptance numbers — stated rather than invented. The next nightly writes the real numbers into measurement_record, and the drift check then reports any contradiction with last_measured on the PR that carries it."
29
29
  },
30
- "removed_2026_08_04": "unpacked_size_mb (max 28) \u2014 removed by maintainer decision at the 9.17.0 release: the gate turned every legitimate payload addition into a blocked release (measured 28.22 vs max 28 with all functional gates green), and the maintainer judged tarball size not worth gating. evaluator_umbrella.sh still MEASURES and records unpacked_size_mb as evidence; only the budget enforcement is gone. ADR-204 review_trigger (a) fired and was resolved this way.",
30
+ "removed_2026_08_04": "unpacked_size_mb (max 28) — removed by maintainer decision at the 9.17.0 release: the gate turned every legitimate payload addition into a blocked release (measured 28.22 vs max 28 with all functional gates green), and the maintainer judged tarball size not worth gating. evaluator_umbrella.sh still MEASURES and records unpacked_size_mb as evidence; only the budget enforcement is gone. ADR-204 review_trigger (a) fired and was resolved this way.",
31
31
  "budgets": {
32
32
  "node_modules_mb": {
33
33
  "max": 140,
@@ -58,18 +58,18 @@
58
58
  "deterministic": false
59
59
  },
60
60
  "cli_help_command_count": {
61
- "max": 107,
62
- "last_measured": 107,
63
- "last_measured_at": "2026-08-23",
64
- "method": "registry enumeration \u2014 count of `{ name: '...', disposition` entries in src/cli/registry.ts (NOT --help prose parsing; methods historically disagreed 74 vs 76 vs 79)",
65
- "baseline_note": "80 \u2192 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) \u2014 the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design \u2014 the next registry addition must move this number in its own PR. 81 \u2192 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 \u2192 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 \u2192 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 \u2014 the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 \u2192 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 \u2014 replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 \u2192 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination \u2014 the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88. 88 \u2192 89 on 2026-08-08: the `council:status` verb registers in the same PR that adds the surface, per this record's own contract. It exists because an agent in a consumer project announced \"kein Council konfiguriert (keine .agent-settings.yml)\" and substituted a weaker path while the council was configured user-globally the whole time \u2014 there was no verb that answered availability, so the only route was an inference from a filename, and the intuitive filename is the one location ADR-104 guarantees is never consulted. Re-measured via the pinned method: 89. 89 \u2192 91 on 2026-08-08: the `self-repair:status` + `self-repair:release` verbs (the queued-defect reader and the single Hard-Floor-gated outward step of the self-repair loop \u2014 the loop is deliberately unable to publish unless a human runs the release command) register in the same PR that adds the surface, per this record's own contract. Landed alongside the +1 council:status move in the same branch. Re-measured via the pinned method: 91. 91 \u2192 94 on 2026-08-08: the `packs:active`, `settings:get` and `mcp:available` verbs (road-to-capability-answerability Phase 2 \u2014 the three capability probes for the gaps that had none) register in the same PR that adds the surface, per this record's own contract. Each answers a question that was previously only inferable from a filename: which packs are active and from which file, what a setting resolves to and which file set it, and what is declared in mcp.json versus what can actually launch. 94 -> 95 in the same PR: `brand:status` (Phase 2.4 \u2014 brand-layer presence, which the rule depended on and no surface could answer). Re-measured twice via the pinned method on the unchanged tree: 95/95. 95 \u2192 96 on 2026-08-10: the `session:recycle` verb (road-to-token-economy-recycling Phase 2.2 \u2014 the deterministic producer of the main-session recycle envelope; the recycle advisory names this exact verb, so it must exist as a shell surface) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 96. 96 -> 97 on 2026-08-10: the `gates` verb registers in the same PR that adds the surface, per this record's own contract. It exists because the blocker fields the dashboard already parses (Owner, What to do, Resolved when \u2014 CI-enforced by lint_roadmap_blockers) had no owner-filtered reader: the dashboard counts the open blockers across a 600-line file and links each to a per-roadmap anchor, so \"which of these are mine\" was a manual read of every anchor. The same inference-from-a-filename shape as the council:status entry above, one layer up. This branch and the session:recycle branch each measured 96 independently and landed on the same number for different verbs; the merge makes it 97, re-measured twice via the pinned method on the merged tree: 97/97. 97 -> 98 on 2026-08-15: the `workspace:doctor` verb (road-to-inbox-harvest-2026-08-c-workspace-identity Phase 3 \u2014 the read-only report over the new `workspaceIdentity()` resolver) registers in the same PR that adds the surface, per this record's own contract. It exists for the same inference-from-a-filename shape as the council:status and gates entries above, one layer down: the tree answered \"where am I\" in eight ad-hoc places across six files, and the 12.0.0 span shipped the same worktree misclassification twice, so no verb could be asked which checkout is the main one. Read-only by construction \u2014 the roadmap's Non-goals put worktree disposal out of scope and its Risk 3 names \"the pressure read becomes a disposal path by accident\" as the failure to design against, so the command carries no --fix and no --prune. Re-measured twice via the pinned method on the unchanged tree: 98/98. 98 -> 99 on 2026-08-17: the `council:quota` verb (road-to-council-quota-accounting-truth Phase 2) registers in the same PR that adds the surface, per this record's own contract. Exactly the inference-from-a-filename shape as the council:status entry above, one layer down: `cmd_quota` had existed in council_cli.ts and been reachable only via `scripts-run`, so the documented recovery path for an exhausted shared counter -- read the usage, reset one provider -- did not resolve through `agent-config`, and an operator debugging a quota failure met `unknown command`. The verb is read-only apart from the pre-existing `--reset <provider>`, which already required `--confirm`. Re-measured twice via the pinned method on the unchanged tree: 99/99. 99 -> 100 on 2026-08-19: the `decision:memo` verb (road-to-long-horizon-execution Phase 2.2, sequencing UOTL Phase 4.3 -- the decision-memo channel) registers in the same PR that adds the surface, per this record's own contract. It exists because the question ladder gained a rung between \"halt and ask\" and \"decide silently\": a resolution the run makes without contacting the operator is only legitimate if it is reviewable afterwards, and there was no surface that wrote such a record with a fixed shape. Write-and-list only, local-only (agents/runtime/ is gitignored), and it gates nothing -- the locked decision classes are refused at the config schema, never in the ledger. 100 -> 101 in the same PR: `run:supervise` (Phase 3.1 -- the out-of-process watcher for runs whose session died with open steps left). It is the operator-facing half of session continuity: nothing anywhere had the job of noticing that a claimed run stopped moving, so a roadmap 40% done and a roadmap finished looked identical from outside the dead session. Report-only by default and it NEVER merges, pushes or closes -- the auto-merge the reference design carries is a named rejection in the roadmap's harvest section, not an unbuilt feature. Re-measured twice via the pinned method on the unchanged tree: 101/101. 101 \u2192 102 on 2026-08-22: the `adr:effective` verb (road-to-evidence-based-adr-governance step 2.2 \u2014 the effective-state projection over one decision record) registers in the same PR that adds the surface, per this record's own contract. It exists because current truth about an ADR was only reconstructable from linear prose: an agent had to read the body, then every amendment, and decide for itself which clauses still stand. The verb reports status, the Decision verbatim, clauses the record's own amendments superseded, active amendments, the three descriptive axes and the review-trigger state. It AUTHORIZES NOTHING \u2014 Phase 2 of that roadmap is titled \"surfacing only; no authority\" and its AC-7 forbids any authority consequence, so the verb reports an absent axis as absent (`\u2014 (no provenance axis)`, `\u2014 (ungraded)`, `absent \u2192 evidence`) and an unresolvable trigger as `indeterminate` rather than inferring one. Re-measured twice via the pinned method on the unchanged tree: 102/102. 102 \u2192 104 on 2026-08-22: the `council:grant-billing` + `council:revoke-billing` verbs (road-to-billing-cliff-gate Phase 2 \u2014 the run-scoped billing grant that lets `ai_council.fallback.api_on_quota: 'ask'` be answered once per run instead of once per seat) register in the same PR that adds the surface, per this record's own contract. The two are a pair by construction rather than by convenience: a grant that can be issued and not revoked would outlive its run, which is the failure the run-scoped TTL exists to prevent. Re-measured via the pinned method: 104. 104 -> 106 on 2026-08-23: the `ui:audit` + `ui:render` verbs (road-to-frontend-power E2.1 and E3.1 -- the two Class-A commands that give the frontend obligations an artefact a gate can read and a render a verdict can cite) register in the same PR that adds the surface, per this record's own contract. The two are a pair by construction rather than by convenience: `ui-audit-gate`'s enforced_by moved from `none` to a carrier in the same change, and that carrier reports `verification: degraded` whenever the render artefact is absent -- so an audit verb without a render verb would ship a gate that can never reach `verified`. Both are Class A under ADR-124: they terminate, their whole state is a rebuildable directory under agents/runtime/state/, and ui:render closes chromium in a `finally` on every path with no --serve, watch or cache for a resident browser to hide in. Re-measured via the pinned method on the unchanged tree: 106. 106 \u2192 107 on 2026-08-23: the `roadmap:context` verb (road-to-roadmap-situational-awareness \u2014 the single live probe that answers what else is in flight before a roadmap is picked) registers in the same PR that adds the surface, per this record's own contract. Its branch measured 105 against a base of 104 and this branch measured 106 against the same base for `ui:audit` + `ui:render`; the merge makes it 107, re-measured on the merged tree via the pinned method (registry enumeration): 107."
61
+ "max": 109,
62
+ "last_measured": 109,
63
+ "last_measured_at": "2026-08-26",
64
+ "method": "registry enumeration — count of `{ name: '...', disposition` entries in src/cli/registry.ts (NOT --help prose parsing; methods historically disagreed 74 vs 76 vs 79)",
65
+ "baseline_note": "80 → 81 on 2026-08-03 (release 9.15.0 gate). This RECORDS growth that already shipped through its own reviewed PR; it does not authorize new surface. The +1 is f02db54c2 (fix(cli): register routing:doctor in the CLI registry) — the command existed, only its registry entry was missing, and the registering PR did not move this budget. The gate did its job again: breach WARNS on main and BLOCKS on release, which is the conscious-decision point rather than a silently raised cap. Re-measured 2026-08-03 via the pinned method: 81. Headroom stays zero by design — the next registry addition must move this number in its own PR. 81 → 82 on 2026-08-04: the `handoff` subcommand (road-to-agent-handoff-resume Phase 4) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 82. 82 → 84 on 2026-08-04: the `route:explain` + `route:audit` verbs (routing-correctness validation surface) register in the same PR that adds the surface. Re-measured via the pinned method: 84. 84 → 85 on 2026-08-05: the `settings:set` verb (road-to-zero-ceremony-settings Phase 2 — the one agent-reachable settings writer) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 85. 85 → 86 on 2026-08-06: the `conformance:behavior` verb (road-to-agent-behavior-conformance Phase 5 — replays the local transcript store through the four mechanised conformance checks) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 86. 86 → 88 on 2026-08-07: the `sessions:list` + `sessions:claim` verbs (road-to-parallel-session-coordination — the shell surface of the shared session register, needed because /roadmap:next is command markdown and can only reach the register through a shell call) register in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 88. 88 → 89 on 2026-08-08: the `council:status` verb registers in the same PR that adds the surface, per this record's own contract. It exists because an agent in a consumer project announced \"kein Council konfiguriert (keine .agent-settings.yml)\" and substituted a weaker path while the council was configured user-globally the whole time — there was no verb that answered availability, so the only route was an inference from a filename, and the intuitive filename is the one location ADR-104 guarantees is never consulted. Re-measured via the pinned method: 89. 89 → 91 on 2026-08-08: the `self-repair:status` + `self-repair:release` verbs (the queued-defect reader and the single Hard-Floor-gated outward step of the self-repair loop — the loop is deliberately unable to publish unless a human runs the release command) register in the same PR that adds the surface, per this record's own contract. Landed alongside the +1 council:status move in the same branch. Re-measured via the pinned method: 91. 91 → 94 on 2026-08-08: the `packs:active`, `settings:get` and `mcp:available` verbs (road-to-capability-answerability Phase 2 — the three capability probes for the gaps that had none) register in the same PR that adds the surface, per this record's own contract. Each answers a question that was previously only inferable from a filename: which packs are active and from which file, what a setting resolves to and which file set it, and what is declared in mcp.json versus what can actually launch. 94 -> 95 in the same PR: `brand:status` (Phase 2.4 — brand-layer presence, which the rule depended on and no surface could answer). Re-measured twice via the pinned method on the unchanged tree: 95/95. 95 → 96 on 2026-08-10: the `session:recycle` verb (road-to-token-economy-recycling Phase 2.2 — the deterministic producer of the main-session recycle envelope; the recycle advisory names this exact verb, so it must exist as a shell surface) registers in the same PR that adds the surface, per this record's own contract. Re-measured via the pinned method: 96. 96 -> 97 on 2026-08-10: the `gates` verb registers in the same PR that adds the surface, per this record's own contract. It exists because the blocker fields the dashboard already parses (Owner, What to do, Resolved when — CI-enforced by lint_roadmap_blockers) had no owner-filtered reader: the dashboard counts the open blockers across a 600-line file and links each to a per-roadmap anchor, so \"which of these are mine\" was a manual read of every anchor. The same inference-from-a-filename shape as the council:status entry above, one layer up. This branch and the session:recycle branch each measured 96 independently and landed on the same number for different verbs; the merge makes it 97, re-measured twice via the pinned method on the merged tree: 97/97. 97 -> 98 on 2026-08-15: the `workspace:doctor` verb (road-to-inbox-harvest-2026-08-c-workspace-identity Phase 3 — the read-only report over the new `workspaceIdentity()` resolver) registers in the same PR that adds the surface, per this record's own contract. It exists for the same inference-from-a-filename shape as the council:status and gates entries above, one layer down: the tree answered \"where am I\" in eight ad-hoc places across six files, and the 12.0.0 span shipped the same worktree misclassification twice, so no verb could be asked which checkout is the main one. Read-only by construction — the roadmap's Non-goals put worktree disposal out of scope and its Risk 3 names \"the pressure read becomes a disposal path by accident\" as the failure to design against, so the command carries no --fix and no --prune. Re-measured twice via the pinned method on the unchanged tree: 98/98. 98 -> 99 on 2026-08-17: the `council:quota` verb (road-to-council-quota-accounting-truth Phase 2) registers in the same PR that adds the surface, per this record's own contract. Exactly the inference-from-a-filename shape as the council:status entry above, one layer down: `cmd_quota` had existed in council_cli.ts and been reachable only via `scripts-run`, so the documented recovery path for an exhausted shared counter -- read the usage, reset one provider -- did not resolve through `agent-config`, and an operator debugging a quota failure met `unknown command`. The verb is read-only apart from the pre-existing `--reset <provider>`, which already required `--confirm`. Re-measured twice via the pinned method on the unchanged tree: 99/99. 99 -> 100 on 2026-08-19: the `decision:memo` verb (road-to-long-horizon-execution Phase 2.2, sequencing UOTL Phase 4.3 -- the decision-memo channel) registers in the same PR that adds the surface, per this record's own contract. It exists because the question ladder gained a rung between \"halt and ask\" and \"decide silently\": a resolution the run makes without contacting the operator is only legitimate if it is reviewable afterwards, and there was no surface that wrote such a record with a fixed shape. Write-and-list only, local-only (agents/runtime/ is gitignored), and it gates nothing -- the locked decision classes are refused at the config schema, never in the ledger. 100 -> 101 in the same PR: `run:supervise` (Phase 3.1 -- the out-of-process watcher for runs whose session died with open steps left). It is the operator-facing half of session continuity: nothing anywhere had the job of noticing that a claimed run stopped moving, so a roadmap 40% done and a roadmap finished looked identical from outside the dead session. Report-only by default and it NEVER merges, pushes or closes -- the auto-merge the reference design carries is a named rejection in the roadmap's harvest section, not an unbuilt feature. Re-measured twice via the pinned method on the unchanged tree: 101/101. 101 → 102 on 2026-08-22: the `adr:effective` verb (road-to-evidence-based-adr-governance step 2.2 — the effective-state projection over one decision record) registers in the same PR that adds the surface, per this record's own contract. It exists because current truth about an ADR was only reconstructable from linear prose: an agent had to read the body, then every amendment, and decide for itself which clauses still stand. The verb reports status, the Decision verbatim, clauses the record's own amendments superseded, active amendments, the three descriptive axes and the review-trigger state. It AUTHORIZES NOTHING — Phase 2 of that roadmap is titled \"surfacing only; no authority\" and its AC-7 forbids any authority consequence, so the verb reports an absent axis as absent (`— (no provenance axis)`, `— (ungraded)`, `absent → evidence`) and an unresolvable trigger as `indeterminate` rather than inferring one. Re-measured twice via the pinned method on the unchanged tree: 102/102. 102 → 104 on 2026-08-22: the `council:grant-billing` + `council:revoke-billing` verbs (road-to-billing-cliff-gate Phase 2 — the run-scoped billing grant that lets `ai_council.fallback.api_on_quota: 'ask'` be answered once per run instead of once per seat) register in the same PR that adds the surface, per this record's own contract. The two are a pair by construction rather than by convenience: a grant that can be issued and not revoked would outlive its run, which is the failure the run-scoped TTL exists to prevent. Re-measured via the pinned method: 104. 104 -> 106 on 2026-08-23: the `ui:audit` + `ui:render` verbs (road-to-frontend-power E2.1 and E3.1 -- the two Class-A commands that give the frontend obligations an artefact a gate can read and a render a verdict can cite) register in the same PR that adds the surface, per this record's own contract. The two are a pair by construction rather than by convenience: `ui-audit-gate`'s enforced_by moved from `none` to a carrier in the same change, and that carrier reports `verification: degraded` whenever the render artefact is absent -- so an audit verb without a render verb would ship a gate that can never reach `verified`. Both are Class A under ADR-124: they terminate, their whole state is a rebuildable directory under agents/runtime/state/, and ui:render closes chromium in a `finally` on every path with no --serve, watch or cache for a resident browser to hide in. Re-measured via the pinned method on the unchanged tree: 106. 106 → 107 on 2026-08-23: the `roadmap:context` verb (road-to-roadmap-situational-awareness — the single live probe that answers what else is in flight before a roadmap is picked) registers in the same PR that adds the surface, per this record's own contract. Its branch measured 105 against a base of 104 and this branch measured 106 against the same base for `ui:audit` + `ui:render`; the merge makes it 107, re-measured on the merged tree via the pinned method (registry enumeration): 107. 107 → 108 on 2026-08-26: the `roadmap:set-step` verb (road-to-skill-ecosystem-runtime-enforcement Phase 6 — the single sanctioned writer of a checkbox glyph) registers in the same PR that adds the surface, per this record's own contract. It exists because the glyph is written today by whatever edits the file, and a concurrent writer destroys work SILENTLY: the loser of an overwrite receives no error. The verb carries an advisory lock, a line-anchored edit that cannot span entries even in principle, a step-count invariant asserted against the LIVE pre-write file rather than an in-memory snapshot, and a post-write survival check. Re-measured via the pinned method (registry enumeration) on the unchanged tree: 108. 108 → 109 on 2026-08-26: the `stubs:due` verb (road-to-inbox-harvest-2026-08-f-owner-decision-queue step 2.1 — the read-only reader over `agents/roadmaps/stubs/` frontmatter) registers in the same PR that adds the surface, per this record's own contract. It exists because step 1.2 backfills a `review_by:` date into 77 parked files, and an AI council (2026-08-26, 2/2) made the ordering a RULE rather than a preference: dates without a reader are strictly worse than no dates, because a stale date certifies attention nobody paid. The verb is read-only by construction — it authors nothing under `agents/roadmaps/stubs/`, so `check_no_stub_inventory_table` stays green and unmodified, and `roadmap:progress` consumes only its two COUNTS for the dashboard header (two integers, no rows, nothing for the deleted index tables to grow back from). Re-measured via the pinned method (registry enumeration) on the unchanged tree: 109."
66
66
  },
67
67
  "mcp_public_tool_count": {
68
68
  "max": 20,
69
69
  "last_measured": 20,
70
70
  "last_measured_at": "2026-08-17",
71
71
  "method": "tools/list length on the stdio server (post-ADR-132: implemented tools only)",
72
- "baseline_note": "19 \u2192 20 on 2026-08-17 (release 13.0.0 gate). The +1 is 866bd9861 (feat(mcp): recover what the host dropped \u2014 real ranker tool + a route to it, road-to-inbox-harvest-2026-08-d-runtime-skill-routing Phase 4): `suggest_skill_for_task` was promoted from a discovery STUB to a real ALLOWLIST entry and removed from STUB_TOOLS. Worth stating precisely, because the consumer-visible NAME did not grow \u2014 the stub already published that name and its `task` + `limit` input schema, which the promotion carried over verbatim. What grew is the count of tools tools/list actually returns, which is exactly what this metric measures post-ADR-132: implemented tools only. Same shape as the cli_help_command_count history above \u2014 this RECORDS growth that already shipped through its own reviewed PR (866bd9861 is on main), it does not authorize new surface. The registering PR did not move this budget, so the gate did its job: the breach warned on main and blocked on the release ref, which is the conscious-decision point rather than a silently raised cap. Re-measured twice via the pinned method on a freshly built dist/mcp/server.mjs: 20/20. Headroom stays zero by design \u2014 the next tool that leaves STUB_TOOLS must move this number in its own PR."
72
+ "baseline_note": "19 → 20 on 2026-08-17 (release 13.0.0 gate). The +1 is 866bd9861 (feat(mcp): recover what the host dropped — real ranker tool + a route to it, road-to-inbox-harvest-2026-08-d-runtime-skill-routing Phase 4): `suggest_skill_for_task` was promoted from a discovery STUB to a real ALLOWLIST entry and removed from STUB_TOOLS. Worth stating precisely, because the consumer-visible NAME did not grow — the stub already published that name and its `task` + `limit` input schema, which the promotion carried over verbatim. What grew is the count of tools tools/list actually returns, which is exactly what this metric measures post-ADR-132: implemented tools only. Same shape as the cli_help_command_count history above — this RECORDS growth that already shipped through its own reviewed PR (866bd9861 is on main), it does not authorize new surface. The registering PR did not move this budget, so the gate did its job: the breach warned on main and blocked on the release ref, which is the conscious-decision point rather than a silently raised cap. Re-measured twice via the pinned method on a freshly built dist/mcp/server.mjs: 20/20. Headroom stays zero by design — the next tool that leaves STUB_TOOLS must move this number in its own PR."
73
73
  }
74
74
  }
75
75
  }