@event4u/agent-config 16.2.0 → 16.4.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 (651) 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 +337 -234
  5. package/README.md +15 -13
  6. package/agents/templates/.ai-council.yml.example +26 -8
  7. package/dist/agent-src/commands/analyze/inbox.md +11 -8
  8. package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
  9. package/dist/agent-src/commands/bug/fix.md +17 -2
  10. package/dist/agent-src/commands/bug/investigate.md +1 -1
  11. package/dist/agent-src/commands/commit/in-chunks.md +40 -31
  12. package/dist/agent-src/commands/commit.md +72 -33
  13. package/dist/agent-src/commands/condense.md +2 -8
  14. package/dist/agent-src/commands/council/debate.md +11 -7
  15. package/dist/agent-src/commands/council/default.md +10 -9
  16. package/dist/agent-src/commands/council.md +1 -1
  17. package/dist/agent-src/commands/estimate-ticket.md +1 -1
  18. package/dist/agent-src/commands/feature/explore.md +3 -3
  19. package/dist/agent-src/commands/feature/plan.md +2 -2
  20. package/dist/agent-src/commands/feature/roadmap.md +1 -1
  21. package/dist/agent-src/commands/fix/ci.md +18 -4
  22. package/dist/agent-src/commands/fix/commit-messages.md +48 -23
  23. package/dist/agent-src/commands/fix/pr-comments.md +3 -6
  24. package/dist/agent-src/commands/implement-ticket.md +4 -4
  25. package/dist/agent-src/commands/jira-ticket.md +1 -1
  26. package/dist/agent-src/commands/memory/add.md +4 -16
  27. package/dist/agent-src/commands/memory/load.md +5 -6
  28. package/dist/agent-src/commands/memory/promote.md +3 -16
  29. package/dist/agent-src/commands/mission/upgrade.md +3 -2
  30. package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
  31. package/dist/agent-src/commands/optimize/deep.md +4 -2
  32. package/dist/agent-src/commands/optimize/rtk.md +4 -26
  33. package/dist/agent-src/commands/pr/create/description-only.md +18 -15
  34. package/dist/agent-src/commands/pr/create.md +42 -34
  35. package/dist/agent-src/commands/pr/merge.md +136 -9
  36. package/dist/agent-src/commands/prepare-for-review.md +13 -11
  37. package/dist/agent-src/commands/project/analyze.md +7 -35
  38. package/dist/agent-src/commands/refine-ticket.md +1 -1
  39. package/dist/agent-src/commands/review/changes.md +14 -19
  40. package/dist/agent-src/commands/roadmap/create.md +1 -1
  41. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  42. package/dist/agent-src/commands/roadmap/next.md +10 -1
  43. package/dist/agent-src/commands/roadmap/process-full.md +56 -42
  44. package/dist/agent-src/commands/roadmap/resolve-blockers.md +411 -0
  45. package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
  46. package/dist/agent-src/commands/roadmap.md +18 -4
  47. package/dist/agent-src/commands/tests/create.md +17 -3
  48. package/dist/agent-src/commands/tests/execute.md +22 -5
  49. package/dist/agent-src/commands/worktree/create.md +7 -3
  50. package/dist/agent-src/commands/worktree/verify.md +2 -1
  51. package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  52. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  53. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
  54. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
  55. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
  56. package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
  57. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +7 -7
  58. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
  59. package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
  60. package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
  61. package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
  62. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
  63. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +99 -54
  64. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  65. package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
  66. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
  67. package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
  68. package/dist/agent-src/contexts/execution/toolchain-resolver.md +95 -7
  69. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  70. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  71. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  72. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  73. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  74. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
  75. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  76. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  77. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
  78. package/dist/agent-src/guidelines/php/git.md +15 -2
  79. package/dist/agent-src/rules/active-remediation.md +1 -2
  80. package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
  81. package/dist/agent-src/rules/architecture.md +0 -1
  82. package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
  83. package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
  84. package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
  85. package/dist/agent-src/rules/autonomous-execution.md +1 -1
  86. package/dist/agent-src/rules/brand-consistency.md +0 -1
  87. package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
  88. package/dist/agent-src/rules/broken-access-control.md +1 -1
  89. package/dist/agent-src/rules/cli-output-handling.md +0 -1
  90. package/dist/agent-src/rules/code-comment-discipline.md +0 -1
  91. package/dist/agent-src/rules/code-provenance.md +0 -1
  92. package/dist/agent-src/rules/command-suggestion-policy.md +1 -1
  93. package/dist/agent-src/rules/commit-conventions.md +1 -2
  94. package/dist/agent-src/rules/communication-through-line.md +1 -2
  95. package/dist/agent-src/rules/content-quoting-floor.md +1 -2
  96. package/dist/agent-src/rules/context-hygiene.md +6 -6
  97. package/dist/agent-src/rules/copilot-routing.md +1 -2
  98. package/dist/agent-src/rules/council-availability.md +4 -4
  99. package/dist/agent-src/rules/cross-source-consistency.md +4 -6
  100. package/dist/agent-src/rules/decision-revisit-gate.md +17 -35
  101. package/dist/agent-src/rules/delegation-policy.md +2 -3
  102. package/dist/agent-src/rules/design-fidelity.md +12 -16
  103. package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
  104. package/dist/agent-src/rules/devcontainer-routing.md +1 -2
  105. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
  106. package/dist/agent-src/rules/docker-commands.md +0 -1
  107. package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
  108. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -1
  109. package/dist/agent-src/rules/domain-safety-pii.md +1 -1
  110. package/dist/agent-src/rules/domain-safety-retention.md +1 -1
  111. package/dist/agent-src/rules/downstream-changes.md +0 -1
  112. package/dist/agent-src/rules/engineering-safety-floor.md +1 -1
  113. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  114. package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
  115. package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
  116. package/dist/agent-src/rules/fast-path-marker-visibility.md +2 -2
  117. package/dist/agent-src/rules/finance-safety-floor.md +1 -1
  118. package/dist/agent-src/rules/fix-what-you-see.md +6 -32
  119. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
  120. package/dist/agent-src/rules/git-history-discipline.md +2 -2
  121. package/dist/agent-src/rules/guidelines.md +0 -1
  122. package/dist/agent-src/rules/history-discipline.md +0 -1
  123. package/dist/agent-src/rules/icon-consistency.md +0 -1
  124. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -1
  125. package/dist/agent-src/rules/improve-before-implement.md +0 -1
  126. package/dist/agent-src/rules/invite-challenge.md +0 -1
  127. package/dist/agent-src/rules/laravel-routing.md +1 -2
  128. package/dist/agent-src/rules/laravel-translations.md +0 -1
  129. package/dist/agent-src/rules/legal-safety-floor.md +3 -3
  130. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -1
  131. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
  132. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -1
  133. package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
  134. package/dist/agent-src/rules/media-governance-routing.md +13 -17
  135. package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
  136. package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
  137. package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
  138. package/dist/agent-src/rules/missing-tool-handling.md +0 -1
  139. package/dist/agent-src/rules/model-recommendation.md +0 -1
  140. package/dist/agent-src/rules/neighbour-precedence.md +64 -0
  141. package/dist/agent-src/rules/no-attribution-footers.md +0 -1
  142. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
  143. package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
  144. package/dist/agent-src/rules/no-roadmap-references.md +0 -1
  145. package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
  146. package/dist/agent-src/rules/onboarding-gate.md +0 -1
  147. package/dist/agent-src/rules/output-discipline.md +0 -1
  148. package/dist/agent-src/rules/package-ci-checks.md +0 -1
  149. package/dist/agent-src/rules/persona-governance.md +4 -5
  150. package/dist/agent-src/rules/php-coding.md +0 -1
  151. package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
  152. package/dist/agent-src/rules/preservation-guard.md +0 -1
  153. package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -4
  154. package/dist/agent-src/rules/question-not-instruction.md +1 -1
  155. package/dist/agent-src/rules/reviewer-awareness.md +0 -1
  156. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
  157. package/dist/agent-src/rules/roadmap-progress-sync.md +4 -7
  158. package/dist/agent-src/rules/role-mode-adherence.md +0 -1
  159. package/dist/agent-src/rules/rule-type-governance.md +0 -1
  160. package/dist/agent-src/rules/runtime-safety.md +1 -1
  161. package/dist/agent-src/rules/scale-discipline.md +0 -1
  162. package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
  163. package/dist/agent-src/rules/security-sensitive-stop.md +3 -3
  164. package/dist/agent-src/rules/self-repair-loop.md +0 -1
  165. package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
  166. package/dist/agent-src/rules/session-canary.md +7 -62
  167. package/dist/agent-src/rules/settings-ask-protocol.md +6 -6
  168. package/dist/agent-src/rules/size-enforcement.md +0 -1
  169. package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
  170. package/dist/agent-src/rules/skill-quality.md +0 -1
  171. package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
  172. package/dist/agent-src/rules/source-confidentiality.md +1 -1
  173. package/dist/agent-src/rules/source-discovery-gate.md +0 -1
  174. package/dist/agent-src/rules/source-of-truth.md +0 -1
  175. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
  176. package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
  177. package/dist/agent-src/rules/symfony-routing.md +1 -2
  178. package/dist/agent-src/rules/think-before-action.md +0 -1
  179. package/dist/agent-src/rules/token-budget-discipline.md +12 -46
  180. package/dist/agent-src/rules/token-efficiency.md +0 -1
  181. package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
  182. package/dist/agent-src/rules/tool-safety.md +1 -1
  183. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  184. package/dist/agent-src/rules/untrusted-input-defense.md +1 -1
  185. package/dist/agent-src/rules/upstream-proposal.md +0 -1
  186. package/dist/agent-src/rules/user-interaction.md +0 -1
  187. package/dist/agent-src/rules/user-interrupt-priority.md +1 -1
  188. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  189. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  190. package/dist/agent-src/scripts/gate_budget.ts +47 -23
  191. package/dist/agent-src/scripts/gate_execute.ts +12 -4
  192. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  193. package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
  194. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
  195. package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
  196. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
  197. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  198. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  199. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  200. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  201. package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
  202. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
  203. package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
  204. package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
  205. package/dist/agent-src/skills/database/data/manifest.json +2 -2
  206. package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
  207. package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
  208. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  209. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  210. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +2 -2
  211. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  212. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  213. package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
  214. package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
  215. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
  216. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  217. package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
  218. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  219. package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
  220. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  221. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  222. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  223. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  224. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  225. package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
  226. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  227. package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
  228. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
  229. package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
  230. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  231. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +4 -2
  232. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  233. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  234. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  235. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  236. package/dist/agent-src/skills/ui-component-architect/SKILL.md +2 -2
  237. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  238. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  239. package/dist/agent-src/templates/AGENTS.md +1 -1
  240. package/dist/agent-src/templates/agent-settings.md +46 -129
  241. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
  242. package/dist/agent-src/templates/command.md +2 -2
  243. package/dist/agent-src/templates/roadmaps.md +6 -1
  244. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  245. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  246. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  247. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  248. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  249. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  250. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  251. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  252. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  253. package/dist/agent-src/templates/skill.md +1 -1
  254. package/dist/cli/registry.js +2 -1
  255. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  256. package/dist/cli-delegate/check_update_banner.js +207 -120
  257. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  258. package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-5GPULQBE.js} +2797 -338
  259. package/dist/cli-delegate/{chunk-IGD6ERX6.js → chunk-6SRJTYJS.js} +42 -176
  260. package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
  261. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  262. package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
  263. package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
  264. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  265. package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-AED2VQGM.js} +1245 -249
  266. package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
  267. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  268. package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
  269. package/dist/cli-delegate/chunk-F3QDG2GT.js +2569 -0
  270. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-G5VVIZRC.js} +3 -3
  271. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-H76PHZBI.js} +149 -61
  272. package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
  273. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  274. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  275. package/dist/cli-delegate/{chunk-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
  276. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-KXXWJTDO.js} +6 -11
  277. package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
  278. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-MDPPKQCQ.js} +58 -9
  279. package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-MSUL5NYP.js} +5 -5
  280. package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
  281. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  282. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  283. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-PWX7CKMD.js} +4 -4
  284. package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
  285. package/dist/cli-delegate/{chunk-7XGBX6ZH.js → chunk-T7XSJSUQ.js} +1144 -589
  286. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  287. package/dist/cli-delegate/chunk-WQWXGIWB.js +1779 -0
  288. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-XQTPXKFA.js} +1 -1
  289. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  290. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  291. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  292. package/dist/cli-delegate/cmd_analyze_session.js +223 -43
  293. package/dist/cli-delegate/cmd_brand_status.js +3 -2
  294. package/dist/cli-delegate/cmd_conformance.js +1252 -249
  295. package/dist/cli-delegate/cmd_converge.js +3 -3
  296. package/dist/cli-delegate/cmd_doctor.js +19 -9
  297. package/dist/cli-delegate/cmd_doctor_neighbours.js +30 -0
  298. package/dist/cli-delegate/cmd_explain.js +45 -21
  299. package/dist/cli-delegate/cmd_export.js +13 -10
  300. package/dist/cli-delegate/cmd_fleet.js +3 -3
  301. package/dist/cli-delegate/cmd_git_convention.js +1851 -0
  302. package/dist/cli-delegate/cmd_handoff.js +44 -22
  303. package/dist/cli-delegate/cmd_mcp_available.js +3 -2
  304. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  305. package/dist/cli-delegate/cmd_migrate.js +3 -3
  306. package/dist/cli-delegate/cmd_packs_active.js +5 -4
  307. package/dist/cli-delegate/cmd_preflight.js +6 -6
  308. package/dist/cli-delegate/cmd_prune.js +14 -11
  309. package/dist/cli-delegate/cmd_refresh.js +2 -1
  310. package/dist/cli-delegate/cmd_route_audit.js +10 -8
  311. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  312. package/dist/cli-delegate/cmd_session_recycle.js +10 -7
  313. package/dist/cli-delegate/cmd_settings_check.js +54 -7
  314. package/dist/cli-delegate/cmd_settings_get.js +18 -8
  315. package/dist/cli-delegate/cmd_settings_migrate.js +13 -10
  316. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  317. package/dist/cli-delegate/cmd_sync.js +14 -11
  318. package/dist/cli-delegate/cmd_uninstall.js +15 -12
  319. package/dist/cli-delegate/cmd_update.js +7 -7
  320. package/dist/cli-delegate/cmd_upgrade.js +9 -8
  321. package/dist/cli-delegate/cmd_validate.js +15 -12
  322. package/dist/cli-delegate/cmd_versions.js +5 -5
  323. package/dist/cli-delegate/deferral_carry.js +16 -0
  324. package/dist/cli-delegate/gate_budget.js +1 -1
  325. package/dist/cli-delegate/gate_execute.js +3 -3
  326. package/dist/cli-delegate/roadmap_gates.js +6 -6
  327. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  328. package/dist/discovery/deprecation-report.md +1 -1
  329. package/dist/discovery/discovery-manifest.json +232 -141
  330. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  331. package/dist/discovery/discovery-manifest.summary.md +3 -3
  332. package/dist/discovery/dormancy-report.md +1 -1
  333. package/dist/discovery/orphan-report.md +1 -1
  334. package/dist/discovery/packs.json +26 -9
  335. package/dist/discovery/trust-report.md +3 -3
  336. package/dist/discovery/workspaces.json +7 -4
  337. package/dist/hooks/dispatch.js +5655 -6623
  338. package/dist/hooks/dispatch.sha256 +1 -1
  339. package/dist/install/claudePathsPlan.js +47 -6
  340. package/dist/install/claudeRuleRewrite.js +7 -0
  341. package/dist/install/emit_host_rules_cli.js +39 -36
  342. package/dist/install/globalRuleScope.js +87 -0
  343. package/dist/install/host_rule_ownership.js +160 -0
  344. package/dist/install/install.mjs +2336 -1249
  345. package/dist/install/installThinLayer.js +289 -0
  346. package/dist/install/installedRuleLinks.js +262 -0
  347. package/dist/install/wizard-plan.js +24 -0
  348. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  349. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
  350. package/dist/mcp/registry-manifest.json +5 -5
  351. package/dist/mcp/server.json +2 -2
  352. package/dist/mcp/server.mjs +36504 -30986
  353. package/dist/router.json +1 -1
  354. package/dist/scripts/_lib/agent_settings.js +26 -120
  355. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  356. package/dist/scripts/_lib/compile_time_toggles.js +12 -21
  357. package/dist/scripts/_lib/git_convention.js +232 -0
  358. package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
  359. package/dist/scripts/_lib/installed_layer.js +704 -0
  360. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  361. package/dist/scripts/_lib/package_root.js +68 -0
  362. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  363. package/dist/scripts/_lib/rule_injection.js +67 -10
  364. package/dist/scripts/_lib/rule_law_section.js +122 -0
  365. package/dist/scripts/_lib/settings_removed_keys.js +168 -0
  366. package/dist/scripts/_lib/thin_rules.js +535 -0
  367. package/dist/scripts/_lib/windsurf_render.js +60 -0
  368. package/dist/scripts/condense.js +14 -26
  369. package/dist/scripts/project_thin_rules.js +14 -294
  370. package/dist/server/app.js +2 -1
  371. package/dist/server/gitKeysGate.js +105 -0
  372. package/dist/server/routes/settings.js +67 -8
  373. package/dist/server/routes/wizard.js +4 -0
  374. package/dist/server/schemas/settings.js +29 -81
  375. package/dist/shared/skillRanking.js +103 -16
  376. package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
  377. package/dist/ui/index.html +1 -1
  378. package/docs/MIGRATION.md +72 -1
  379. package/docs/contracts/settings-classes.md +39 -67
  380. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  381. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  382. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  383. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  384. package/docs/guidelines/agent-infra/layered-settings.md +13 -1
  385. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  386. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  387. package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
  388. package/docs/guidelines/php/git.md +15 -2
  389. package/package.json +1 -1
  390. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  391. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  392. package/src/agent-src/scripts/gate_budget.ts +47 -23
  393. package/src/agent-src/scripts/gate_execute.ts +12 -4
  394. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  395. package/src/agent-src/templates/AGENTS.md +1 -1
  396. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  397. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  398. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  399. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  400. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  401. package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  402. package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  403. package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  404. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  405. package/src/config/agent-settings.template.yml +141 -334
  406. package/src/config/agents-paths.yml +16 -0
  407. package/src/config/assurance-capability-registry.json +7 -3
  408. package/src/config/ci-local-parity.yml +3 -0
  409. package/src/config/continuity-surface.json +10 -3
  410. package/src/config/discovery/packs.yml +17 -1
  411. package/src/config/evaluator-budgets.json +23 -10
  412. package/src/config/gate-coverage.yml +138 -3
  413. package/src/config/gate-violation-baselines.json +64 -16
  414. package/src/config/gitignore-block.txt +19 -0
  415. package/src/config/hook-bundle-budget.json +25 -0
  416. package/src/config/hook-token-budget.json +6 -1
  417. package/src/config/host-instruction-limits.json +33 -0
  418. package/src/config/release-gate-locality.yml +2 -1
  419. package/src/config/routing-coverage-seed.json +67 -4
  420. package/src/config/rule-activation-census.json +7 -3
  421. package/src/config/rule-consequence-class.json +161 -0
  422. package/src/config/rule-law-ceilings.json +105 -0
  423. package/src/config/rule-obligations.json +833 -0
  424. package/src/install/claudePathsPlan.ts +46 -4
  425. package/src/install/claudeRuleRewrite.ts +10 -1
  426. package/src/install/emit_host_rules_cli.ts +43 -34
  427. package/src/install/globalRuleScope.ts +109 -0
  428. package/src/install/host_rule_ownership.ts +170 -0
  429. package/src/install/installThinLayer.ts +378 -0
  430. package/src/install/installedRuleLinks.ts +308 -0
  431. package/src/install/wizard-plan.ts +24 -0
  432. package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
  433. package/src/scripts/_cli/cmd_conformance.ts +13 -2
  434. package/src/scripts/_cli/cmd_doctor.ts +33 -81
  435. package/src/scripts/_cli/cmd_doctor_neighbours.ts +426 -0
  436. package/src/scripts/_cli/cmd_explain.ts +72 -14
  437. package/src/scripts/_cli/cmd_git_convention.ts +637 -0
  438. package/src/scripts/_cli/cmd_settings_check.ts +66 -8
  439. package/src/scripts/_cli/cmd_settings_get.ts +18 -3
  440. package/src/scripts/_cli/doctor_execution.ts +72 -1
  441. package/src/scripts/_dispatch.bash +53 -4
  442. package/src/scripts/_lib/agent_settings.ts +26 -124
  443. package/src/scripts/_lib/blocked_by_marker.ts +1 -1
  444. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  445. package/src/scripts/_lib/compile_time_toggles.ts +12 -21
  446. package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
  447. package/src/scripts/_lib/estate_offsets.ts +241 -0
  448. package/src/scripts/_lib/exemption_shape.ts +143 -0
  449. package/src/scripts/_lib/fnv.ts +23 -0
  450. package/src/scripts/_lib/foreign_scan.ts +106 -0
  451. package/src/scripts/_lib/git_base_ref.ts +92 -0
  452. package/src/scripts/_lib/git_convention.ts +291 -0
  453. package/src/scripts/_lib/git_convention_carrier.ts +389 -0
  454. package/src/scripts/_lib/git_convention_grammar.ts +246 -0
  455. package/src/scripts/_lib/git_convention_measure.ts +344 -0
  456. package/src/scripts/_lib/gitignore_block.ts +314 -0
  457. package/src/scripts/_lib/global_deploy_inventory.ts +106 -0
  458. package/src/scripts/_lib/graph_feeder_record.ts +437 -0
  459. package/src/scripts/_lib/hook_settings.ts +73 -0
  460. package/src/scripts/_lib/host_capability.ts +40 -19
  461. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  462. package/src/scripts/_lib/installed_layer.ts +963 -0
  463. package/src/scripts/_lib/json_merge.ts +82 -0
  464. package/src/scripts/_lib/json_pointers.ts +93 -11
  465. package/src/scripts/_lib/knowledge_global.ts +14 -1
  466. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  467. package/src/scripts/_lib/machine_wake.ts +16 -3
  468. package/src/scripts/_lib/module_reach.ts +456 -0
  469. package/src/scripts/_lib/neighbour_census.ts +760 -0
  470. package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
  471. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  472. package/src/scripts/_lib/neighbour_tool_use.ts +187 -0
  473. package/src/scripts/_lib/prompt_shape.ts +46 -0
  474. package/src/scripts/_lib/ratification_artifact.ts +220 -1
  475. package/src/scripts/_lib/ratification_subject.ts +92 -0
  476. package/src/scripts/_lib/release_findings_ingest.ts +15 -7
  477. package/src/scripts/_lib/release_highlights.ts +5 -0
  478. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  479. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  480. package/src/scripts/_lib/review_coverage.ts +134 -0
  481. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  482. package/src/scripts/_lib/rule_injection.ts +130 -10
  483. package/src/scripts/_lib/rule_law_section.ts +147 -0
  484. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  485. package/src/scripts/_lib/rule_obligations.ts +205 -0
  486. package/src/scripts/_lib/self_repair.ts +1 -1
  487. package/src/scripts/_lib/settings_removed_keys.ts +173 -0
  488. package/src/scripts/_lib/skill_origin.ts +254 -0
  489. package/src/scripts/_lib/structured_ask.ts +64 -21
  490. package/src/scripts/_lib/test_red_state.ts +5 -0
  491. package/src/scripts/_lib/thin_rules.ts +620 -0
  492. package/src/scripts/_lib/touched_file_quality.ts +570 -0
  493. package/src/scripts/_lib/turn_end_refusals.ts +77 -2
  494. package/src/scripts/_lib/windsurf_render.ts +63 -0
  495. package/src/scripts/_lib/worker_budget.ts +1 -1
  496. package/src/scripts/adr/regenerate_index.ts +16 -1
  497. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  498. package/src/scripts/ai_council/clients.ts +26 -57
  499. package/src/scripts/ai_council/config.ts +8 -8
  500. package/src/scripts/ai_council/modification_review.ts +100 -0
  501. package/src/scripts/ai_council/modification_review_questions.ts +90 -0
  502. package/src/scripts/ai_council/orchestrator.ts +5 -5
  503. package/src/scripts/ai_council/spend_gate.ts +18 -7
  504. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  505. package/src/scripts/ai_team/config.ts +11 -16
  506. package/src/scripts/audit_skill_overlap.ts +261 -0
  507. package/src/scripts/audit_user_type_axis.ts +20 -8
  508. package/src/scripts/before_complete_hook.ts +243 -12
  509. package/src/scripts/bench_ab_clone.ts +1 -2
  510. package/src/scripts/bench_concern_spawn_path.ts +129 -0
  511. package/src/scripts/bench_graph_feeder_latency.ts +584 -0
  512. package/src/scripts/bench_touched_file_quality.ts +238 -0
  513. package/src/scripts/check_agent_artifact_location.ts +36 -0
  514. package/src/scripts/check_branch_freshness.ts +147 -24
  515. package/src/scripts/check_enforcement_coverage.ts +130 -0
  516. package/src/scripts/check_enforcement_matrix.ts +377 -20
  517. package/src/scripts/check_estate_count.ts +130 -153
  518. package/src/scripts/check_evaluator_budgets.ts +4 -0
  519. package/src/scripts/check_finding_dispositions.ts +196 -21
  520. package/src/scripts/check_gate_coverage.ts +4 -3
  521. package/src/scripts/check_gate_reachability.ts +48 -1
  522. package/src/scripts/check_generator_sync.ts +48 -0
  523. package/src/scripts/check_hook_bundle_composition.ts +477 -0
  524. package/src/scripts/check_kernel_edit_ratified.ts +132 -14
  525. package/src/scripts/check_memory.ts +7 -1
  526. package/src/scripts/check_pack_size.ts +1 -1
  527. package/src/scripts/check_release_highlights.ts +10 -0
  528. package/src/scripts/check_release_manifest_content.ts +189 -0
  529. package/src/scripts/check_release_pr_shape.ts +38 -15
  530. package/src/scripts/check_standing_rule_delivery.ts +129 -13
  531. package/src/scripts/check_suppression_hygiene.ts +2 -5
  532. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  533. package/src/scripts/ci_settle.ts +42 -5
  534. package/src/scripts/classify_merge_risk.ts +320 -0
  535. package/src/scripts/closure_scan.ts +91 -1
  536. package/src/scripts/code_graph/detect.ts +127 -7
  537. package/src/scripts/code_graph/foreign.ts +194 -0
  538. package/src/scripts/code_graph/query.ts +217 -4
  539. package/src/scripts/code_graph/types.ts +26 -2
  540. package/src/scripts/code_graph/validate.ts +3 -1
  541. package/src/scripts/code_graph/verbs.ts +103 -0
  542. package/src/scripts/command_suggester/settings.ts +8 -108
  543. package/src/scripts/command_suggester/types.ts +4 -5
  544. package/src/scripts/compile_hook_manifest.ts +33 -1
  545. package/src/scripts/condense.ts +14 -27
  546. package/src/scripts/consumer_matrix.ts +102 -0
  547. package/src/scripts/context_hygiene_hook.ts +13 -23
  548. package/src/scripts/cost/preflight.mjs +12 -1
  549. package/src/scripts/council_cli.ts +7 -7
  550. package/src/scripts/dispatch_r2_reviewer.ts +24 -11
  551. package/src/scripts/estate_exemption_shape.ts +202 -0
  552. package/src/scripts/explain_run.ts +8 -13
  553. package/src/scripts/generate_git_convention_grammar.ts +127 -0
  554. package/src/scripts/generate_host_cost_table.ts +21 -4
  555. package/src/scripts/handoff_context_hook.ts +86 -37
  556. package/src/scripts/hook_manifest.json +1 -1
  557. package/src/scripts/hook_manifest.yaml +175 -15
  558. package/src/scripts/hooks/block_config_weakening.ts +115 -7
  559. package/src/scripts/hooks/block_plumbing_writes.ts +37 -5
  560. package/src/scripts/hooks/code_graph_context_hook.ts +252 -23
  561. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  562. package/src/scripts/hooks/concern_registry.ts +2 -0
  563. package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
  564. package/src/scripts/hooks/dispatch_hook.ts +52 -52
  565. package/src/scripts/hooks/evidence_independence.ts +12 -4
  566. package/src/scripts/hooks/exit_codes.ts +2 -1
  567. package/src/scripts/hooks/host_lowering.json +1 -1
  568. package/src/scripts/hooks/host_lowering.ts +19 -1
  569. package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
  570. package/src/scripts/hooks/one_question_per_ask_hook.ts +41 -25
  571. package/src/scripts/hooks/payload_stub.ts +10 -1
  572. package/src/scripts/hooks/push_settle_hook.ts +4 -3
  573. package/src/scripts/hooks/rule_inject_hook.ts +795 -60
  574. package/src/scripts/hooks/state_io.ts +8 -4
  575. package/src/scripts/hooks/table_fingerprint.ts +21 -0
  576. package/src/scripts/hooks/telemetry_usage_hook.ts +24 -7
  577. package/src/scripts/hooks/turn_end_gate_hook.ts +85 -0
  578. package/src/scripts/hooks_status.ts +112 -0
  579. package/src/scripts/injection_scan_hook.ts +7 -0
  580. package/src/scripts/install-hooks.sh +42 -14
  581. package/src/scripts/install.ts +78 -215
  582. package/src/scripts/installed_layer_report.ts +103 -0
  583. package/src/scripts/language_mirror_hook.ts +15 -6
  584. package/src/scripts/learning_sidecar.ts +119 -8
  585. package/src/scripts/lint_blocker_citations.ts +198 -0
  586. package/src/scripts/lint_evidence_artifacts.ts +9 -0
  587. package/src/scripts/lint_hook_concern_budget.ts +10 -21
  588. package/src/scripts/lint_hook_manifest.ts +53 -0
  589. package/src/scripts/lint_major_migration_sections.ts +156 -26
  590. package/src/scripts/lint_pack_boundaries.ts +465 -29
  591. package/src/scripts/lint_roadmap_blockers.ts +282 -29
  592. package/src/scripts/lint_roadmap_complexity.ts +4 -2
  593. package/src/scripts/lint_rule_law_section.ts +647 -0
  594. package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
  595. package/src/scripts/lint_settings_classes.ts +1 -1
  596. package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
  597. package/src/scripts/lint_workflow_security.ts +173 -6
  598. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  599. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  600. package/src/scripts/measure_routing_signal.ts +54 -16
  601. package/src/scripts/measure_skill_ranker_baseline.ts +221 -8
  602. package/src/scripts/memory_learn_hook.ts +91 -6
  603. package/src/scripts/model_rule_injection.ts +55 -8
  604. package/src/scripts/onboarding_gate_hook.ts +7 -6
  605. package/src/scripts/print_required_checks.ts +15 -3
  606. package/src/scripts/probe_host_compliance.ts +33 -5
  607. package/src/scripts/probe_turnaround.ts +183 -3
  608. package/src/scripts/project_thin_rules.ts +34 -327
  609. package/src/scripts/ratification_header.ts +77 -0
  610. package/src/scripts/refusal_envelope.ts +138 -0
  611. package/src/scripts/release_publication.ts +29 -3
  612. package/src/scripts/report_dispatch_import_closure.ts +76 -0
  613. package/src/scripts/report_evidence_temperature.ts +657 -0
  614. package/src/scripts/report_installed_rule_links.ts +274 -0
  615. package/src/scripts/report_label_agreement.ts +233 -0
  616. package/src/scripts/report_module_reach.ts +212 -0
  617. package/src/scripts/report_obligation_mechanism.ts +228 -0
  618. package/src/scripts/report_parked_blockers.ts +222 -0
  619. package/src/scripts/report_required_checks_drift.ts +196 -0
  620. package/src/scripts/report_single_token_triggers.ts +277 -0
  621. package/src/scripts/report_skill_ranker_confusion.ts +543 -0
  622. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  623. package/src/scripts/report_verification_record_coverage.ts +306 -0
  624. package/src/scripts/routing_doctor.ts +2 -2
  625. package/src/scripts/rule_activation_census.ts +5 -2
  626. package/src/scripts/rule_trigger_eval.ts +9 -9
  627. package/src/scripts/schemas/agent-settings.schema.json +17 -31
  628. package/src/scripts/schemas/command.schema.json +1 -1
  629. package/src/scripts/schemas/review-findings.schema.json +3 -2
  630. package/src/scripts/schemas/rule.schema.json +5 -0
  631. package/src/scripts/schemas/skill.schema.json +1 -1
  632. package/src/scripts/self_review_gate.ts +101 -9
  633. package/src/scripts/skill_tools/score_skill_relevance.ts +314 -40
  634. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  635. package/src/scripts/sync_gitignore.ts +29 -235
  636. package/src/scripts/sync_pr_branch.ts +403 -132
  637. package/src/scripts/trigger_eval_grandfather.json +0 -21
  638. package/src/server/schemas/settings.ts +42 -176
  639. package/src/shared/skillRanking.ts +169 -14
  640. package/dist/cli-delegate/chunk-5R7HOLAF.js +0 -99
  641. package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
  642. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
  643. package/src/scripts/_lib/config_chain.ts +0 -477
  644. package/src/scripts/_lib/conformance_report.ts +0 -403
  645. package/src/scripts/_lib/eval_discrimination.ts +0 -95
  646. package/src/scripts/_lib/evaluator_promotion.ts +0 -225
  647. package/src/scripts/_lib/file_slicer.ts +0 -117
  648. package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
  649. package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
  650. package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
  651. package/src/scripts/_lib/role_split.ts +0 -338
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "$comment": "Violation ratchet for gates whose dead scan root was repaired. A repair REVEALS pre-existing debt; it does not create it. Each entry records the count revealed at repair time — the gate fails only when its count RISES. Lowering a count is a normal commit; raising one is a defect. Entries expire: a baseline that has not dropped within 56 days of `landed` (or of `reaffirmed.date`) fails its gate, because a number that never moves is suppression with extra steps. Mechanism + rationale: src/scripts/_lib/gate_baseline.ts. Decision: AI council 2026-08-02, roadmap road-to-gates-that-can-fail blocker `dead-gate-finding-triage`.",
3
3
  "gates": {
4
+ "lint_blocker_citations": {
5
+ "count": 10,
6
+ "landed": "2026-10-06",
7
+ "falsifier": "./scripts-run src/scripts/lint_blocker_citations # lists every miss; it fails when the count RISES above this entry",
8
+ "note": "Blocker citations (`path:line`) in the `## Blockers` section of active roadmaps and stubs whose file does not resolve, measured on main @ adaad0aa2 when the lint landed (road-to-parked-blockers-that-get-asked step 5.1, decision D3). All 10 are a bare basename or a partial path (`chairman.ts:71-76`, `archive/road-to-session-closeout.md:182`) that resolves neither from the repository root nor from the citing roadmap's directory; none is a line beyond the end of an existing file. A ratchet rather than a hard fail because line citations drift with every edit above them, so an existing miss is drift rather than a new defect. Each one clears by writing the citation repository-relative, or deleting it when its target is gone; the count only falls."
9
+ },
4
10
  "check_claims:non-inference": {
5
11
  "count": 40,
6
12
  "landed": "2026-08-26",
@@ -15,6 +21,10 @@
15
21
  "check_depth_budget": {
16
22
  "count": 4,
17
23
  "landed": "2026-08-06",
24
+ "reaffirmed": {
25
+ "date": "2026-10-02",
26
+ "reason": "Re-derived today rather than waved through, and the re-derivation found something the count cannot express: the FILE COUNT is unchanged at 4, while the debt behind it has roughly doubled. Measured now against the figures this entry's own note recorded on 2026-08-06 — roadmap-process-loop.md 20,360 -> 61,147 (3x), design-antipatterns.md 20,707 -> 32,486, orchestration-telemetry.md 16,155 -> 21,033, rule-body-migration-inventory.md 23,782 -> 23,782 (the only one that held). Total excess over the 16,000-char ceiling went from ~16,600 to ~73,800 chars while the ratchet read a flat 4 and never fired. That is the shape the 56-day clause exists to expose, and it is why this reaffirmation records the growth instead of restating the note. NOT CLEARED, for the reason the original note gives and which still holds: splitting four large reference documents is unrelated to the change in hand, and the P4 migration pattern that feeds them is live — prose moves INTO these files by design, so they grow as the kernel shrinks. Lowering the count means splitting at least one, which is an estate decision about the declarative layer's shape, not cleanup inside an unrelated PR. SURFACED to the owner in the same session as a follow-up: a per-file-count ratchet is the wrong instrument for a population that grows in place, and a total-excess ratchet (the shape check_source_size_budget already uses in this same file) would have fired months ago. Revisit-if: the shape decision is taken, a fifth file crosses the ceiling, or roadmap-process-loop.md is split — whichever comes first. Expires 2026-11-27 (56 days), by which point the shape question is owed an answer rather than a second reaffirmation."
27
+ },
18
28
  "note": "Four depth files exceed the 16,000-char per-file ceiling: rule-body-migration-inventory.md (23,782), design-antipatterns.md (20,707), roadmap-process-loop.md (20,360), orchestration-telemetry.md (16,155). Recorded rather than fixed because splitting four large reference documents is unrelated to the change that introduced the ceiling, and a gate that lands as four instant blockers is the shape this repository has already recorded as a failure. Shrink-only from here: a FIFTH over-ceiling file reds. roadmap-process-loop.md is the file that motivated the gate — it states 'Size budget: <= 4,000 chars' in its own header and is 5x over it, which is what a declared budget with nothing measuring it decays into. The ceiling is a GROWTH RATCHET, not a measured quality threshold: the 7,308-trajectory study behind the 3,500-token skill ceiling (ADR-217) was taken on procedural always-co-loaded skills, and this layer is declarative and loaded one or two files at a time. Replace the number when someone measures comprehension on THIS layer."
19
29
  },
20
30
  "check_gate_completeness": {
@@ -34,10 +44,10 @@
34
44
  "note": "The nine active non-draft roadmaps that predate the `relates:` requirement (road-to-agentic-engineering-assurance, road-to-component-library-lifecycle, road-to-council-evidence-integrity, road-to-frontend-fidelity-calibration, road-to-monorepo-scope-and-detection, road-to-observability-plate, road-to-role-scoped-spawn-profiles, road-to-skill-delivery-over-mcp, road-to-standing-payload-diet). This is a NEW obligation rather than a repaired scan root, and the ratchet is the point: `depends:` shipped in the template with nothing requiring it and measured 0 adoption, so requiring `relates:` retroactively across the estate would be an owner-reserved write with no analysis behind the edges it would have to invent (held as step 4.3, deferred). Clearing an entry here is one roadmap at a time: run `agent-config roadmap:context` on it, write the rows the probe surfaces, and lower the count."
35
45
  },
36
46
  "check_source_size_budget": {
37
- "count": 17745,
38
- "landed": "2026-09-30",
39
- "note": "LOWERING 2026-09-30, 17,746 -> 17,745 — a lowering commit, and the gate asked for it by name. The direction is the surprising one again: this branch ADDED a feature to `install.ts` (an opt-in host env write) and that file came out SHORTER than it went in, 5,270 -> 5,269. The whole mechanism — the two-row allow table, the settings reader, the env-block builder and the bridge wrapper — lives in the new under-cap `src/scripts/_lib/host_env_write.ts`, so `install.ts` pays ONE import line and one expression for it; and the three-line `for` loop over healed plugin ids in the same function collapsed to one, which is inside the function the change already edits. The gain is a MOVE plus one tightening, never a deletion: nothing was dropped and nothing was swept. That module boundary is also the better one on its own terms — one place now owns which host variable this package may write, which is the question the owner decision of 2026-09-30 turns on. LOCAL READING, on the same discriminator every entry below uses: the gate walks authored source under `src/`, and `git status --porcelain -uall -- src` reported ZERO untracked files, so a clean CI checkout of this commit measures the same 17,745. If CI reads anything else, CI's number is the correct one and this note is the record of why. `landed` is refreshed deliberately: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,746 while the tree measures 17,745 would never expire at any age. PRIOR ENTRY: LOWERING 2026-09-29, 17,748 -> 17,746 — a lowering commit, same doctrine as every entry below, and the gate asked for it by name. This branch ADDED two gate scripts, a guard and a shared lib under `src/`, so the direction is the surprising one and worth stating: the new files each land under their own cap and contribute zero EXCESS, while factoring the shell write shapes out of `block_kernel_rule_writes` into `_lib/shell_write_shapes.ts` moved lines out of a file that was over its cap and into one that is not. Net -2. LOCAL READING, on the same discriminator every entry below uses: the gate walks authored source under `src/`, and `git status --porcelain -uall -- src` reported ZERO untracked files, so a clean CI checkout of this commit measures the same 17,746. If CI reads anything else, CI's number is the correct one and this note is the record of why. `landed` is refreshed deliberately: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,748 while the tree measures 17,746 would never expire at any age. PRIOR ENTRY: LOWERING 2026-09-29, 17,762 -> 17,748 — a lowering commit, same doctrine as every entry below, and the gate asked for it by name. Reporting the host traffic environment in `doctor` needed a new surface; rather than pay those lines against `src/scripts/_cli/cmd_doctor.ts`, already far over the cap, the whole network-posture block moved out into the new under-cap `src/scripts/_cli/doctor_network_posture.ts`, which is also where the new logic lives: one module owns which traffic variables exist, how each is read, and how an absent one is reported, so the unit is coherent rather than a line-count trim. cmd_doctor.ts 3,618 -> 3,604; total 17,762 -> 17,748. The gain is a MOVE, not a deletion — nothing was dropped and nothing was swept. `landed` is refreshed deliberately, for the reason the prior entries record: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,762 while the tree measures 17,748 would never expire at any age, and the gate only ADVISES on a loose ratchet while `check_source_size_budget.test.ts` blocks — that asymmetry is what forces a lowering commit to carry its own baseline update. PRIOR ENTRY: LOWERING 2026-09-27, 17,765 -> 17,762 — the second half of the same repair, and a lowering for the same reason. Closing the remaining preservation defects needed lines in two over-cap files: `src/scripts/install.ts` (route the generated Claude Desktop marker through the tracker, hand the rule-rewrite its skip set) and `src/server/routes/wizard.ts` (surface the conflict count, stop reporting exit 3 as a failure). Both were paid from the same subject rather than from the ratchet: `_files_by_tool_from_bridges` joined its sibling in `src/install/manifestFiles.ts`, which now owns the whole per-tool inventory, and the wizard's exit-code semantics moved into `src/install/preserve.ts` beside `installDoneSummary`, which already lives there for this exact reason. install.ts 5,277 -> 5,270; wizard.ts 1,500 -> 1,504. PRIOR ENTRY: LOWERING 2026-09-27, 17,784 -> 17,765 — a lowering commit, same doctrine as the entry it replaces. Repairing the install-manifest digest loss needed new state in `_update_installed_tools_manifest` (a recorded-inventory read, a preserved-path index, a reconciliation call). Rather than pay that against `src/scripts/install.ts`, already 3,777 over the cap, the manifest file-inventory block (`_sha256_of_file`, `_file_entry`, `_files_by_tool_from_deploy` — 29 lines) moved out into the under-cap `src/install/manifestFiles.ts`, which is where the new logic lives too: one module now owns what the manifest's per-tool `files[]` holds, how it is read back, and how the two reconcile, so the unit is coherent rather than a line-count trim. install.ts 5,296 -> 5,277; total 17,784 -> 17,765. PRIOR ENTRY: LOWERING 2026-09-20, 17,858 -> 17,784 — a lowering commit, not a reconciliation, but measured under the same doctrine the four entries below carry: the committed number is the gate's own reading on the MERGED tree, taken after origin/main was merged into drain/headless-log-write rather than from either side. The branch's transaction-log write added 27 lines to `src/scripts/install.ts`, already 3,897 over the cap, taking the total to 17,885. Rather than pay that, the `json.dumps` byte-parity block (`jsonStrNoAscii`, `_jsonScalar`, `_dumpIndent`, `jsonDumpsIndent`, `jsonDumpsCompact` — 101 lines) moved out of `install.ts` into the under-cap `src/scripts/_lib/json_python_parity.ts`: pure, total functions of their input carrying no installer state, so the unit is coherent rather than a line-count trim. install.ts 5,397 -> 5,296; total 17,885 -> 17,784, a net -74 against the prior baseline. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-14, 17,861 -> 17,858 — the FOURTH reconciliation of this entry, same doctrine as the three below: the committed number is the gate's own reading on the MERGED tree, never either side's. Neither branch earned the -3; it falls out of main having absorbed drain/release-head-field, whose `derive_head_prefill` extraction moved the span-to-prefill composition into an under-cap module. Taking this branch's 17,861 would have silently given that gain back. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-13, 17,863 -> 17,861 — the THIRD reconciliation of this entry in one day, and re-measured on the merged tree rather than taken from either side, which is the only resolution that converges. drain/adversarial-verification reached 17,864 by paying for a `forge_protection` block and a cascade-base module entirely in files under the 1,500-line cap; the incoming reconciliation reached 17,863 from different work. Neither describes the merge. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-13, 17,944/17,866 -> 17,863. drain/decision-closure and drain/breaking-line-contradiction each lowered from the SAME 17,947 base in parallel -- this branch to 17,944 (net -3: the ownership vocabulary, its two Iron-Law sets and the merged default-mode map moved out of ai_council/config.ts into ai_council/ownership_classes.ts, and the settings-rename block moved out of _lib/agent_settings.ts into _lib/settings_renamed_keys.ts, both UNDER the 1500 cap so both cost nothing) and main to 17,866. Taking either side alone is wrong in a different direction, which is the doctrine this entry already carries from 2026-09-03 and 2026-09-07: main's value silently discards this branch's earned -3, and this branch's value RAISES the baseline against main and weakens the gate. The committed number is neither -- it is the gate's own output on the MERGED tree, where both reductions apply. MAIN-SIDE ENTRY, carried so neither branch's record is lost: Lowered 17,947 -> 17,866 on 2026-09-13 by drain/breaking-line-contradiction, on this entry's own doctrine. The branch adds the BACKWARD half of the MIGRATION.md obligation -- a refusal for a major cut whose BREAKING section has no migration entry -- and writing it into release.ts came in at +61, because that file sits ~375 lines PAST the 1500 cap so every line there is one unit. Paid down rather than baselined, and the move was the coherent unit rather than the minimum one: BOTH refusals went, the new backward half and the pre-existing forward half (assert_scheduled_deprecations_clear), into _lib/release_migration_gate.ts at 184 lines and therefore UNDER the cap, so the pair and all their rationale now cost nothing. They moved on merit rather than only on arithmetic -- they are the two halves of one obligation, written eleven months apart, and release.ts held only the two call sites. parse_version stayed module-private in release.ts and the lib carries a two-line _minor_patch instead: exporting a private helper to serve one caller would widen the surface of the file the move exists to narrow. release.ts 1,875 -> 1,733: a branch that ADDED a pipeline refusal leaves the file eighty-one lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports nothing staged and nothing untracked at this commit, so a clean CI checkout measures the same 17,866. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises -- which is how CI found it: the gate exited 0 with a loose-ratchet warning and the test went red. PRIOR ENTRY: Lowered 17,959 -> 17,947 on 2026-09-11 by the findings-ledger branch, on this entry's own doctrine. The branch adds step 7 to release.ts, which sits ~326 lines PAST the 1500 cap so every line there is one unit, and it came in at +145. Paid down rather than baselined, in two moves. `settle_findings_ledger` and `_blocking_without_disposition` moved out of release.ts into _lib/release_findings_ingest.ts -- 95 lines, and that module is under the cap, so the step and its rationale now cost nothing. It moved on merit rather than only on arithmetic: the module already owns every message the step prints and every argv it builds, and release.ts held only the sequencing. Then the `--ci` fallback dispatch of the three tag-triggered workflows -- 24 lines of loop and warning with no reader elsewhere in step 10 -- moved into _lib/release_tag_dispatch.ts, also under the cap. release.ts 1,826 -> 1,814: a branch that ADDED a pipeline step leaves the file twelve lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ file staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,947. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,963 -> 17,959 on 2026-09-09 by feat/cdd-fidelity-council, on the same shape as the entry below and with the same discriminator. The branch's src-link rewrite (a blind review found 253 of 268 links under dist/agent-src/guidelines/ dead, because condense.ts folded only the docs/ prefixes and never (../)+src/rules|skills) came in at +15 excess: condense.ts sits ~1,208 lines PAST the 1500 cap, so every line there is one unit. Paid down rather than baselined, in the way this entry's doctrine prescribes. `_rewrite_body_links` and its two regex constants moved out of condense.ts into _lib/guidelines_lane.ts, 151 lines and therefore UNDER the cap, so the function and its prose now cost nothing. It moved on merit rather than only on arithmetic: every rule the rewriter applies is a statement about which source tree projects where, which is that module's own subject, and condense.ts held it only because that is where the projector lives. condense.ts 2,712 -> 2,708 net, after the one import line and the one call-site rename -- a branch that ADDED a rewrite rule leaves the file four lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ files tracked and nothing untracked, so a clean CI checkout of this commit measures the same 17,959. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,973 -> 17,963 on 2026-09-08 by drain/graph-shipped-close. The branch registers five code-graph MCP tools (road-to-a-graph-that-is-shipped 4.1). Their five records and schemas are ~250 lines, and putting them in mcp_server/tools.ts -- which sits ~500 lines PAST the 1500 cap, so every line there is one unit -- would have cost ~250 excess. They live in mcp_server/graph_tools.ts instead (~280 lines, UNDER the cap, so they and their prose cost nothing), and tools.ts spreads them into ALLOWLIST in two lines: one import and one `...GRAPH_TOOLS,`. Those two were paid for rather than baselined, in the way this entry's doctrine prescribes: `_strip` and `_resolvePath` -- a whitespace trim and a tolerant realpath, generic by nature -- moved out of tools.ts into mcp_server/path_util.ts, also under the cap. They are imported under their original underscore names, so all 28 call sites are unchanged and a two-function move does not read as a sweep. tools.ts 2,025 -> 2,015: -12 from the extraction, +2 from the registration, net -10 for a branch that ADDED a feature. CORRECTED 2026-09-08 after an independent review checked the figure against the tree -- this sentence read '2,025 -> 2,013, net -12, against the +2 the registration needed', which states an intermediate file length as the final one and leaves the arithmetic (-12) and the conclusion (-10) describing different trees. `git show origin/main:...tools.ts | wc -l` is 2025 and the working tree is 2015. The TOTAL, 17,963, was always the gate's own output and is unchanged. Every other file this branch touches or creates -- code_graph/verbs.ts, code_graph/cli.ts, code_graph/build.ts, code_graph/detect.ts, code_graph/query.ts, code_graph/sqlite_store.ts, code_graph/types.ts, _lib/regression_neighbourhood.ts -- is under the 1500 ceiling before and after, so it contributes zero excess whatever it grew by. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,963. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,974 -> 17,973 on 2026-09-08 by drain/topology-c1. The branch adds a live-path emit to council_cli.ts, which sits 2,454 lines PAST the 1500 cap so every line there is one unit, and paid its own way down rather than raising the baseline, in the way this entry's doctrine prescribes. The twelve-line `all_responses` assembly (a spread, three conditionals and a push) moved out of council_cli.ts into ai_council/deliberation_metrics.ts::runCallsFrom, 353 lines and therefore UNDER the cap, so the six stage labels and their prose cost nothing. It moved on merit rather than only on arithmetic: 'which calls did this run make, and at which stage' is that module's own subject, and the CLI held the list only as a flat array with the stage boundaries implicit in the order -- both readings now come out of one walk, so the billing total and the attribution can never be computed over different sets. council_cli.ts 3,955 -> 3,954 net, after the two call lines, the import and the one payload key the feature needed. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,973. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,016 -> 17,974 on 2026-09-07 by fix/single-delivery-unconditional. SETTLED FIGURE, and it supersedes an intra-session 17,962 this same branch committed earlier — read the direction against MAIN, which is what the ratchet protects: main is 18,016, the branch leaves 17,974, net -42. The 17,962 was this branch's own low before a neutral review returned twelve findings; fixing them added a real mechanism to mcp_server and condense.ts (the flat-wrapper carriage gate the review showed was missing, plus its four-skip predicate), and condense.ts sits ~1,215 lines PAST the cap so each of those lines is one unit. Paid down first, in the way this entry's doctrine prescribes: _suggestSkillForTaskHandler and its 18-line docstring moved out of mcp_server/tools.ts (2,079 -> 2,025) into mcp_server/suggest_skill.ts, 72 lines and UNDER the cap, so its prose costs nothing. The residual +12 against the intra-session low is the gate's own output on the settled tree and is recorded rather than engineered away, because the alternative was extracting _nested_command_subpath and its two callers out of condense.ts - which needs MODULE_STATE, _relativeToPosix and _domains_command_logical passed in, a wider diff than the finding warrants and one no review asked for. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the three new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,974. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-07, 18,061/18,017 -> 18,016. drain/admissible-council-seats and fix/release-obligation-answerable each lowered from the SAME 18,062 base in parallel — main to 18,061 (net -1: curlJsonPost, the seat-status helpers and the per-seat config parsing moved out of the three over-ceiling council files) and the branch to 18,017 (net -45: the /dev/tty prompt helpers moved out of release.ts into _lib/tty_prompt.ts, 76 lines and UNDER the cap, taking release.ts 1871 -> 1826). Taking either side alone is wrong in a different direction, which is the reconciliation doctrine this entry already carried from 2026-09-03: main's value silently discards the branch's earned -45, and the branch's value RAISES the baseline against main and weakens the gate. The committed number is neither — it is the gate's own output on the MERGED tree, where both reductions apply, and it equals the arithmetic (18,062 - 45 - 1 = 18,016) rather than being reconciled by it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports ZERO untracked files, so a clean CI checkout of this commit measures the same 18,016. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in the merge commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,062 -> 18,061 on 2026-09-07 by drain/admissible-council-seats. The branch's own additions to the three over-ceiling files (ai_council/config.ts, council_cli.ts, ai_council/clients.ts) came in at +96 excess and were paid down to -1 rather than baselined, in the four ways this entry's doctrine prescribes: `curlJsonPost` moved out of clients.ts into ai_council/api_transport.ts (UNDER the cap, so the prose and the three new provider shims cost nothing); the seat-status helpers moved out of council_cli.ts into ai_council/status_surface.ts, taking an orphaned doc comment with them; the three new per-seat config fields' parsing moved out of config.ts into ai_council/seat_policy.ts::parseSeatFields; and three prose blocks that the branch's own transport repair made FACTUALLY FALSE (the `openai` / `google-genai` Python-SDK claims, and a `_curlJsonPost` pointer to a function that had moved) were corrected and shortened in the same change. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports zero untracked files with the five new src/ files staged, so a clean CI checkout of this commit measures the same 18,061. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried here because tests/scripts/check_source_size_budget.test.ts:166 asserts baseline == live and therefore blocks where the gate only advises -- the lowering commit must carry its own baseline update. Lowered 18,068 -> 18,062 on 2026-09-06 by drain/host-enforcement-truth. Collapsing the five per-host binding constants in install.ts into src/scripts/hooks/host_lowering.yaml removed 29 lines from a file ~3,900 past the 1500 cap, where every line costs one excess; the journal's surface column and its extracted migration helper gave 23 back. Lowered 18,245 -> 18,230 on 2026-09-02 by drain/publication-integrity-option-a. Phase 2 Option A moved the authoring instruction out of the generator: release.ts, which sits ~530 lines PAST the 1500 cap so every line there costs one excess, loses the comment emission, a 16-line HEAD_DEFAULT doc block and its alias const, and gains a shorter writer docstring. The doc block moved to _lib/release_material.ts, which is 289 lines and therefore UNDER the cap, so the same prose now costs nothing. Net -15. The branch first came in at +8 and paid its own way down rather than raising the baseline. BRANCH-SIDE ENTRY: Lowered 17,947 -> 17,944 on 2026-09-13 by drain/decision-closure, on this entry's own doctrine and at the gate's own request. The branch's ownership-axis additions to ai_council/config.ts came in at +86 excess: that file sits ~700 lines PAST the 1500 cap, so every line there is one unit. Paid down rather than baselined, in one move. The eight ownership class names, the two Iron-Law sets, the merged default-mode map and the mode-check function moved out of config.ts into ai_council/ownership_classes.ts -- 91 lines, UNDER the cap, so the vocabulary and its prose now cost nothing. It moved on merit rather than only on arithmetic: the roadmap-side gate lint_decision_classes needs the same eight names and has no business importing the council's whole schema to learn them, and the loader now carries three lines where it carried twenty-four. config.ts 2,182 -> 2,179: a branch that ADDED an entire decision axis leaves the file three lines shorter than it found it. Every other src/ file this branch creates -- lint_decision_classes.ts, lint_roadmap_producers.ts, closure_scan.ts, council_record_shape.ts, scope_growth.ts, ownership_classes.ts -- is under the 1500 ceiling, so it contributes zero excess whatever it grew by. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ files tracked and nothing untracked, so a clean CI checkout of this commit measures the same 17,944. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,959 -> 17,947 on 2026-09-11 by the findings-ledger branch, on this entry's own doctrine. The branch adds step 7 to release.ts, which sits ~326 lines PAST the 1500 cap so every line there is one unit, and it came in at +145. Paid down rather than baselined, in two moves. `settle_findings_ledger` and `_blocking_without_disposition` moved out of release.ts into _lib/release_findings_ingest.ts -- 95 lines, and that module is under the cap, so the step and its rationale now cost nothing. It moved on merit rather than only on arithmetic: the module already owns every message the step prints and every argv it builds, and release.ts held only the sequencing. Then the `--ci` fallback dispatch of the three tag-triggered workflows -- 24 lines of loop and warning with no reader elsewhere in step 10 -- moved into _lib/release_tag_dispatch.ts, also under the cap. release.ts 1,826 -> 1,814: a branch that ADDED a pipeline step leaves the file twelve lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ file staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,947. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,963 -> 17,959 on 2026-09-09 by feat/cdd-fidelity-council, on the same shape as the entry below and with the same discriminator. The branch's src-link rewrite (a blind review found 253 of 268 links under dist/agent-src/guidelines/ dead, because condense.ts folded only the docs/ prefixes and never (../)+src/rules|skills) came in at +15 excess: condense.ts sits ~1,208 lines PAST the 1500 cap, so every line there is one unit. Paid down rather than baselined, in the way this entry's doctrine prescribes. `_rewrite_body_links` and its two regex constants moved out of condense.ts into _lib/guidelines_lane.ts, 151 lines and therefore UNDER the cap, so the function and its prose now cost nothing. It moved on merit rather than only on arithmetic: every rule the rewriter applies is a statement about which source tree projects where, which is that module's own subject, and condense.ts held it only because that is where the projector lives. condense.ts 2,712 -> 2,708 net, after the one import line and the one call-site rename -- a branch that ADDED a rewrite rule leaves the file four lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ files tracked and nothing untracked, so a clean CI checkout of this commit measures the same 17,959. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,973 -> 17,963 on 2026-09-08 by drain/graph-shipped-close. The branch registers five code-graph MCP tools (road-to-a-graph-that-is-shipped 4.1). Their five records and schemas are ~250 lines, and putting them in mcp_server/tools.ts -- which sits ~500 lines PAST the 1500 cap, so every line there is one unit -- would have cost ~250 excess. They live in mcp_server/graph_tools.ts instead (~280 lines, UNDER the cap, so they and their prose cost nothing), and tools.ts spreads them into ALLOWLIST in two lines: one import and one `...GRAPH_TOOLS,`. Those two were paid for rather than baselined, in the way this entry's doctrine prescribes: `_strip` and `_resolvePath` -- a whitespace trim and a tolerant realpath, generic by nature -- moved out of tools.ts into mcp_server/path_util.ts, also under the cap. They are imported under their original underscore names, so all 28 call sites are unchanged and a two-function move does not read as a sweep. tools.ts 2,025 -> 2,015: -12 from the extraction, +2 from the registration, net -10 for a branch that ADDED a feature. CORRECTED 2026-09-08 after an independent review checked the figure against the tree -- this sentence read '2,025 -> 2,013, net -12, against the +2 the registration needed', which states an intermediate file length as the final one and leaves the arithmetic (-12) and the conclusion (-10) describing different trees. `git show origin/main:...tools.ts | wc -l` is 2025 and the working tree is 2015. The TOTAL, 17,963, was always the gate's own output and is unchanged. Every other file this branch touches or creates -- code_graph/verbs.ts, code_graph/cli.ts, code_graph/build.ts, code_graph/detect.ts, code_graph/query.ts, code_graph/sqlite_store.ts, code_graph/types.ts, _lib/regression_neighbourhood.ts -- is under the 1500 ceiling before and after, so it contributes zero excess whatever it grew by. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,963. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,974 -> 17,973 on 2026-09-08 by drain/topology-c1. The branch adds a live-path emit to council_cli.ts, which sits 2,454 lines PAST the 1500 cap so every line there is one unit, and paid its own way down rather than raising the baseline, in the way this entry's doctrine prescribes. The twelve-line `all_responses` assembly (a spread, three conditionals and a push) moved out of council_cli.ts into ai_council/deliberation_metrics.ts::runCallsFrom, 353 lines and therefore UNDER the cap, so the six stage labels and their prose cost nothing. It moved on merit rather than only on arithmetic: 'which calls did this run make, and at which stage' is that module's own subject, and the CLI held the list only as a flat array with the stage boundaries implicit in the order -- both readings now come out of one walk, so the billing total and the attribution can never be computed over different sets. council_cli.ts 3,955 -> 3,954 net, after the two call lines, the import and the one payload key the feature needed. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,973. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,016 -> 17,974 on 2026-09-07 by fix/single-delivery-unconditional. SETTLED FIGURE, and it supersedes an intra-session 17,962 this same branch committed earlier — read the direction against MAIN, which is what the ratchet protects: main is 18,016, the branch leaves 17,974, net -42. The 17,962 was this branch's own low before a neutral review returned twelve findings; fixing them added a real mechanism to mcp_server and condense.ts (the flat-wrapper carriage gate the review showed was missing, plus its four-skip predicate), and condense.ts sits ~1,215 lines PAST the cap so each of those lines is one unit. Paid down first, in the way this entry's doctrine prescribes: _suggestSkillForTaskHandler and its 18-line docstring moved out of mcp_server/tools.ts (2,079 -> 2,025) into mcp_server/suggest_skill.ts, 72 lines and UNDER the cap, so its prose costs nothing. The residual +12 against the intra-session low is the gate's own output on the settled tree and is recorded rather than engineered away, because the alternative was extracting _nested_command_subpath and its two callers out of condense.ts - which needs MODULE_STATE, _relativeToPosix and _domains_command_logical passed in, a wider diff than the finding warrants and one no review asked for. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the three new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,974. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-07, 18,061/18,017 -> 18,016. drain/admissible-council-seats and fix/release-obligation-answerable each lowered from the SAME 18,062 base in parallel — main to 18,061 (net -1: curlJsonPost, the seat-status helpers and the per-seat config parsing moved out of the three over-ceiling council files) and the branch to 18,017 (net -45: the /dev/tty prompt helpers moved out of release.ts into _lib/tty_prompt.ts, 76 lines and UNDER the cap, taking release.ts 1871 -> 1826). Taking either side alone is wrong in a different direction, which is the reconciliation doctrine this entry already carried from 2026-09-03: main's value silently discards the branch's earned -45, and the branch's value RAISES the baseline against main and weakens the gate. The committed number is neither — it is the gate's own output on the MERGED tree, where both reductions apply, and it equals the arithmetic (18,062 - 45 - 1 = 18,016) rather than being reconciled by it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports ZERO untracked files, so a clean CI checkout of this commit measures the same 18,016. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in the merge commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,062 -> 18,061 on 2026-09-07 by drain/admissible-council-seats. The branch's own additions to the three over-ceiling files (ai_council/config.ts, council_cli.ts, ai_council/clients.ts) came in at +96 excess and were paid down to -1 rather than baselined, in the four ways this entry's doctrine prescribes: `curlJsonPost` moved out of clients.ts into ai_council/api_transport.ts (UNDER the cap, so the prose and the three new provider shims cost nothing); the seat-status helpers moved out of council_cli.ts into ai_council/status_surface.ts, taking an orphaned doc comment with them; the three new per-seat config fields' parsing moved out of config.ts into ai_council/seat_policy.ts::parseSeatFields; and three prose blocks that the branch's own transport repair made FACTUALLY FALSE (the `openai` / `google-genai` Python-SDK claims, and a `_curlJsonPost` pointer to a function that had moved) were corrected and shortened in the same change. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports zero untracked files with the five new src/ files staged, so a clean CI checkout of this commit measures the same 18,061. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried here because tests/scripts/check_source_size_budget.test.ts:166 asserts baseline == live and therefore blocks where the gate only advises -- the lowering commit must carry its own baseline update. Lowered 18,068 -> 18,062 on 2026-09-06 by drain/host-enforcement-truth. Collapsing the five per-host binding constants in install.ts into src/scripts/hooks/host_lowering.yaml removed 29 lines from a file ~3,900 past the 1500 cap, where every line costs one excess; the journal's surface column and its extracted migration helper gave 23 back. Lowered 18,245 -> 18,230 on 2026-09-02 by drain/publication-integrity-option-a. Phase 2 Option A moved the authoring instruction out of the generator: release.ts, which sits ~530 lines PAST the 1500 cap so every line there costs one excess, loses the comment emission, a 16-line HEAD_DEFAULT doc block and its alias const, and gains a shorter writer docstring. The doc block moved to _lib/release_material.ts, which is 289 lines and therefore UNDER the cap, so the same prose now costs nothing. Net -15. The branch first came in at +8 and paid its own way down rather than raising the baseline.",
40
- "reason": "Lowered 18,230 -> 18,209 on 2026-09-03 by drain/artifact-location. `doctor --strict` needed 16 lines of integration wiring in cmd_doctor.ts, which sits ~2,100 lines PAST the 1500 cap so every line there costs one excess. The branch first came in at +137 and paid its own way down rather than raising the baseline: the strict semantics, threshold, kill switch, payload helper and argv fragments moved to _cli/_doctor_strict.ts (~160 lines, under the cap, costs nothing), taking it to +15; then the 37-line drift renderer moved to _cli/_doctor_emit.ts. Net -21. The renderer was chosen deliberately: pure rendering, two dependencies, no argparse involvement and therefore none of the byte-parity risk the parser surface carries against the retired Python implementation; nothing outside cmd_doctor.ts imported it. An AI council on the residual split (a: raise by 15 / d: descope the feature); neither was taken, because a parallel branch demonstrated the same day that paying down is achievable in this codebase, which is the evidence the split lacked. This gate's own test comment prescribes it: a commit that splits a god-file lowers the excess and must carry the lowered baseline. MERGE RECONCILIATION 2026-09-03, 18,209 -> 18,205: drain/wired-instruments and drain/artifact-location each lowered from the SAME 18,230 base in parallel -- the branch to 18,226 (net -4, run_continuation_hook.ts's termination ladder moved to _lib/continuation_ladder.ts and runtime_journal.ts's prose to _lib/outcome_vocabularies.ts, both under the cap) and main to 18,209 (net -21, the doctor --strict split above). Taking either side alone is wrong in a different direction: main's value silently discards the branch's earned -4, and the branch's value RAISES the baseline against main and weakens the gate. The committed number is neither -- it is the gate's own output on the merged tree, where both reductions apply. THIS LOCAL READING IS ADMISSIBLE HERE, and the discriminator matters because this file's ci-parity:local-only entry records a 165 -> 164 lowering that was reverted for exactly the opposite case: that count depends on how the environment resolves the projection surface, whereas this gate walks only SOURCE_ROOTS = ['src'] (check_source_size_budget.ts:88) counting excess lines over the 1500 ceiling, and `git status --porcelain -uall -- src/` reported ZERO untracked files, so a clean CI checkout of this commit measures the same 18,205. If CI reads anything else, CI's number is the correct one and this note is the record of why. LOWERED 18,205 -> 18,193 on 2026-09-03 by fix/release-curation-ask. The change adds a fifth publication guard, and its own additions landed at +10 excess: release.ts 2,008 -> 2,018, every line of which is past the 1500 cap. Paid down rather than baselined, in the two ways this gate's doctrine prescribes. The guard's rationale (~13 lines of docstring, including why prMerged is a parameter rather than a call-site if) lives in release_publication.ts, 915 lines and therefore UNDER the cap, so the prose costs nothing; and the two pure text helpers _splitlines and _rstrip moved out of release.ts into release_env.ts (333 lines, also under the cap), taking release.ts to 1,996 -- 12 BELOW where it started. The branch came in at +10 and leaves at -12. Recorded while moving them: _splitlines is duplicated a third and fourth time at adoption_report.ts:106 and readme_linter.ts:418; collapsing all three onto one definition touches three modules and was left out of this change rather than done silently. LOWERED 18,193 -> 18,180 on 2026-09-03 by fix/release-branch-reuse. The step-1 branch decision -- twenty lines of if/else in release.ts -- became one call to checkout_release_branch in release_publication.ts, which is 1,019 lines and therefore UNDER the 1500 cap, so the twenty lines plus a ~35-line rationale now cost nothing. release.ts 1,996 -> 1,983, every one of those lines being past the cap. The drill grew 765 -> 918 for two new scenarios and the snapshot/restore that keeps them from writing the real CHANGELOG, and it is under the cap too. A change that adds a feature and lowers the excess is the shape this gate's doctrine asks for; the alternative was a +13 raise for logic that had no business in the god-file. LOWERED 18,180 -> 18,068 on 2026-09-05 by fix/release-gate-producer-parity. The change wires the governance-mix obligation into the writer and the two local guards and adds a release-gate locality registry; its own additions to release.ts landed at +19 excess, every one of those lines past the 1500 cap. Paid down rather than baselined, in the way this entry's doctrine prescribes: the 132-line test-count-trend unit (_TEST_COUNT_LINE_RE, _TEST_LIST_MAX_BUFFER, _count_from_list_result, _count_tests_current, _previous_test_count_from_changelog, _render_test_trend_line) moved from release.ts into release_publication.ts, which is under the cap and where it now belongs on merit rather than only on arithmetic -- the same diff makes the missing `Tests: N` footer a section-level publication blocker, so the writer that emits the footer and the guard that refuses its absence sit in one module. release.ts 1,983 -> 1,871. All four names are re-exported from release.ts, so tests/scripts/release.test.ts is unchanged. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the ceiling, and `git status --porcelain -uall -- src/` reports ZERO untracked files with the two new src/ files staged, so a clean CI checkout of this commit measures the same 18,068. If CI reads anything else, CI's number is the correct one and this note is the record of why."
47
+ "count": 17516,
48
+ "landed": "2026-10-09",
49
+ "note": "LOWERING 2026-10-09, 17,550 -> 17,516 — the gate asked for it by name after `REMOVED_KEYS` and its once-per-run warning moved out of `src/scripts/_lib/agent_settings.ts` (1,510 lines) into `src/scripts/_lib/settings_removed_keys.ts`, so the settings-key retirement batch adds its registry entries in a file under the ceiling instead of growing the excess; the retirement itself also deletes legacy rename-map rows and the setup-hint settings read from `src/scripts/install.ts`. Earlier: LOWERING 2026-10-05, 17,571 -> 17,550 — a lowering commit, and the gate asked for it BY NAME: it reported `ratchet is loose` and named 17,550; `check_source_size_budget.test.ts` then pins baseline == live total, so this is required rather than optional. The gain IS this branch's own work and it is a DEDUPLICATION, which this convention accepts: all five CliClient subclass constructors forwarded six option fields to super() by name, which is why a seventh (`consumer`) was silently dropped and every CLI call booked as `unknown`. Replacing the five field lists with `{ ...opts, model: ... }` removes 27 lines from src/scripts/ai_council/clients.ts (2,858 -> 2,831) against the +6 the consumer fix added, so the net is -21. No ceiling was edited and no file was split to game the metric. The count is tree-derived (line counts over src/**/*.ts) and container-independent, unlike the projection-surface gates whose local readings diverge. Verified with `npx tsc --noEmit` clean and the clients suite green in this checkout. PRIOR ENTRY: LOWERING 2026-10-05, 17,585 -> 17,571 — a lowering commit, and the gate asked for it BY NAME: it reported `ratchet is loose` and named 17,571. The gain IS this branch's own work and it is an EXTRACTION, which is the only shape this convention accepts: road-to-an-installed-layer-that-is-thinned step 1.1 adds a thinning call to the global deploy loop, and pays for those lines by moving `_resolve_global_rule_scope` out of `src/scripts/install.ts` into `src/install/globalRuleScope.ts` behind a same-signature wrapper, and removes the two imports the extraction orphaned (install.ts 5,180 -> 5,156). The user-global whitelist rows in `src/scripts/_lib/agent_settings.ts` push that file 1,499 -> 1,510, so the net is -5 rather than -15. No ceiling was edited and no file was split to game the metric. Verified by running the gate in this worktree after `npx tsc --noEmit` passed clean. PRIOR ENTRY: LOWERING 2026-10-02, 17,620 -> 17,592 — a lowering commit, and the gate asked for it BY NAME: it reported `ratchet is loose` and named 17,592. The gain IS this branch's own work, and it is a deduplication rather than a sweep. `GLOBAL_DEPLOY_SOURCES` was defined TWICE — in `src/scripts/install.ts` and in `src/install/wizard-plan.ts` — and the two copies were byte-identical across all 18 host rows, which is a duplicate that stays correct exactly until somebody edits one of them. road-to-rule-triggers-and-links-that-hold step 1.2 did that: it added `contexts/` and `guidelines/` to the install.ts copy and the wizard kept installing without them, so the deduplication is the fix for a defect this branch introduced, not an opportunistic tidy. install.ts now imports and re-exports the wizard-plan definition, so every caller is unchanged, and the file goes 5,231 -> 5,175 lines. Verified by running the gate in this worktree after `npm run typecheck` passed clean. PRIOR ENTRY: LOWERING 2026-10-02, 17,734 -> 17,620 — a lowering commit, and the gate asked for it BY NAME: it reported `ratchet is loose` and named 17,620 as the number to write. The gain is not this branch's own work; it is the net of the lanes that merged into main while this branch was in flight, which is exactly the case the clause below exists for — a tree that got smaller while a baseline stood still would let the gain be given back silently by the next change. Verified in a FRESH detached checkout of the pushed head rather than in the working worktree, because the first reading was taken in a tree that had not finished its base sync and reported the two numbers the other way round; the fresh checkout measures 17,620 against a 17,734 baseline over 1,582 scanned files. `landed` is refreshed deliberately, for the reason every entry below gives: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left high while the tree measures lower would never expire at any age. PRIOR ENTRY: LOWERING 2026-10-01, 17,745 -> 17,734 — a lowering commit, and the gate asked for it by name. road-to-a-hook-bundle-with-one-yaml-reader 3.1 split the windsurf renderer out of `condense.ts` into the new under-cap `src/scripts/_lib/windsurf_render.ts`, and `strip_frontmatter` moved with it as the render's one non-trivial dependency. `condense.ts` went 2,728 -> 2,717 excess lines. The direction is honest about its own history: an earlier commit on this branch kept the renderer INLINE in `condense.ts` and CI caught it as 20 new violations — this entry is that fix, not a sweep, and the lowering is the by-product of putting the code where it belonged. Nothing was deleted: the renderer and the stripper are both still called, by TWO callers now rather than one, and `condense.ts` re-exports `strip_frontmatter` so no importer's path changed. The new module lands at 64 lines, far under its own cap, so it contributes zero excess. LOCAL READING, same discriminator every entry below uses: the gate walks authored source under `src/`, and the only untracked path `git status --porcelain -uall -- src` reports is that new module, committed in this same change — so a clean CI checkout of this commit measures the same 17,734. If CI reads anything else, CI's number is the correct one and this note is the record of why. `landed` is refreshed deliberately, for the reason the prior entry gives: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left high while the tree measures lower would never expire at any age. PRIOR ENTRY: LOWERING 2026-09-30, 17,746 -> 17,745 — a lowering commit, and the gate asked for it by name. The direction is the surprising one again: this branch ADDED a feature to `install.ts` (an opt-in host env write) and that file came out SHORTER than it went in, 5,270 -> 5,269. The whole mechanism — the two-row allow table, the settings reader, the env-block builder and the bridge wrapper — lives in the new under-cap `src/scripts/_lib/host_env_write.ts`, so `install.ts` pays ONE import line and one expression for it; and the three-line `for` loop over healed plugin ids in the same function collapsed to one, which is inside the function the change already edits. The gain is a MOVE plus one tightening, never a deletion: nothing was dropped and nothing was swept. That module boundary is also the better one on its own terms — one place now owns which host variable this package may write, which is the question the owner decision of 2026-09-30 turns on. LOCAL READING, on the same discriminator every entry below uses: the gate walks authored source under `src/`, and `git status --porcelain -uall -- src` reported ZERO untracked files, so a clean CI checkout of this commit measures the same 17,745. If CI reads anything else, CI's number is the correct one and this note is the record of why. `landed` is refreshed deliberately: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,746 while the tree measures 17,745 would never expire at any age. PRIOR ENTRY: LOWERING 2026-09-29, 17,748 -> 17,746 — a lowering commit, same doctrine as every entry below, and the gate asked for it by name. This branch ADDED two gate scripts, a guard and a shared lib under `src/`, so the direction is the surprising one and worth stating: the new files each land under their own cap and contribute zero EXCESS, while factoring the shell write shapes out of `block_kernel_rule_writes` into `_lib/shell_write_shapes.ts` moved lines out of a file that was over its cap and into one that is not. Net -2. LOCAL READING, on the same discriminator every entry below uses: the gate walks authored source under `src/`, and `git status --porcelain -uall -- src` reported ZERO untracked files, so a clean CI checkout of this commit measures the same 17,746. If CI reads anything else, CI's number is the correct one and this note is the record of why. `landed` is refreshed deliberately: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,748 while the tree measures 17,746 would never expire at any age. PRIOR ENTRY: LOWERING 2026-09-29, 17,762 -> 17,748 — a lowering commit, same doctrine as every entry below, and the gate asked for it by name. Reporting the host traffic environment in `doctor` needed a new surface; rather than pay those lines against `src/scripts/_cli/cmd_doctor.ts`, already far over the cap, the whole network-posture block moved out into the new under-cap `src/scripts/_cli/doctor_network_posture.ts`, which is also where the new logic lives: one module owns which traffic variables exist, how each is read, and how an absent one is reported, so the unit is coherent rather than a line-count trim. cmd_doctor.ts 3,618 -> 3,604; total 17,762 -> 17,748. The gain is a MOVE, not a deletion — nothing was dropped and nothing was swept. `landed` is refreshed deliberately, for the reason the prior entries record: checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,762 while the tree measures 17,748 would never expire at any age, and the gate only ADVISES on a loose ratchet while `check_source_size_budget.test.ts` blocks — that asymmetry is what forces a lowering commit to carry its own baseline update. PRIOR ENTRY: LOWERING 2026-09-27, 17,765 -> 17,762 — the second half of the same repair, and a lowering for the same reason. Closing the remaining preservation defects needed lines in two over-cap files: `src/scripts/install.ts` (route the generated Claude Desktop marker through the tracker, hand the rule-rewrite its skip set) and `src/server/routes/wizard.ts` (surface the conflict count, stop reporting exit 3 as a failure). Both were paid from the same subject rather than from the ratchet: `_files_by_tool_from_bridges` joined its sibling in `src/install/manifestFiles.ts`, which now owns the whole per-tool inventory, and the wizard's exit-code semantics moved into `src/install/preserve.ts` beside `installDoneSummary`, which already lives there for this exact reason. install.ts 5,277 -> 5,270; wizard.ts 1,500 -> 1,504. PRIOR ENTRY: LOWERING 2026-09-27, 17,784 -> 17,765 — a lowering commit, same doctrine as the entry it replaces. Repairing the install-manifest digest loss needed new state in `_update_installed_tools_manifest` (a recorded-inventory read, a preserved-path index, a reconciliation call). Rather than pay that against `src/scripts/install.ts`, already 3,777 over the cap, the manifest file-inventory block (`_sha256_of_file`, `_file_entry`, `_files_by_tool_from_deploy` — 29 lines) moved out into the under-cap `src/install/manifestFiles.ts`, which is where the new logic lives too: one module now owns what the manifest's per-tool `files[]` holds, how it is read back, and how the two reconcile, so the unit is coherent rather than a line-count trim. install.ts 5,296 -> 5,277; total 17,784 -> 17,765. PRIOR ENTRY: LOWERING 2026-09-20, 17,858 -> 17,784 — a lowering commit, not a reconciliation, but measured under the same doctrine the four entries below carry: the committed number is the gate's own reading on the MERGED tree, taken after origin/main was merged into drain/headless-log-write rather than from either side. The branch's transaction-log write added 27 lines to `src/scripts/install.ts`, already 3,897 over the cap, taking the total to 17,885. Rather than pay that, the `json.dumps` byte-parity block (`jsonStrNoAscii`, `_jsonScalar`, `_dumpIndent`, `jsonDumpsIndent`, `jsonDumpsCompact` — 101 lines) moved out of `install.ts` into the under-cap `src/scripts/_lib/json_python_parity.ts`: pure, total functions of their input carrying no installer state, so the unit is coherent rather than a line-count trim. install.ts 5,397 -> 5,296; total 17,885 -> 17,784, a net -74 against the prior baseline. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-14, 17,861 -> 17,858 — the FOURTH reconciliation of this entry, same doctrine as the three below: the committed number is the gate's own reading on the MERGED tree, never either side's. Neither branch earned the -3; it falls out of main having absorbed drain/release-head-field, whose `derive_head_prefill` extraction moved the span-to-prefill composition into an under-cap module. Taking this branch's 17,861 would have silently given that gain back. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-13, 17,863 -> 17,861 — the THIRD reconciliation of this entry in one day, and re-measured on the merged tree rather than taken from either side, which is the only resolution that converges. drain/adversarial-verification reached 17,864 by paying for a `forge_protection` block and a cascade-base module entirely in files under the 1,500-line cap; the incoming reconciliation reached 17,863 from different work. Neither describes the merge. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-13, 17,944/17,866 -> 17,863. drain/decision-closure and drain/breaking-line-contradiction each lowered from the SAME 17,947 base in parallel -- this branch to 17,944 (net -3: the ownership vocabulary, its two Iron-Law sets and the merged default-mode map moved out of ai_council/config.ts into ai_council/ownership_classes.ts, and the settings-rename block moved out of _lib/agent_settings.ts into _lib/settings_renamed_keys.ts, both UNDER the 1500 cap so both cost nothing) and main to 17,866. Taking either side alone is wrong in a different direction, which is the doctrine this entry already carries from 2026-09-03 and 2026-09-07: main's value silently discards this branch's earned -3, and this branch's value RAISES the baseline against main and weakens the gate. The committed number is neither -- it is the gate's own output on the MERGED tree, where both reductions apply. MAIN-SIDE ENTRY, carried so neither branch's record is lost: Lowered 17,947 -> 17,866 on 2026-09-13 by drain/breaking-line-contradiction, on this entry's own doctrine. The branch adds the BACKWARD half of the MIGRATION.md obligation -- a refusal for a major cut whose BREAKING section has no migration entry -- and writing it into release.ts came in at +61, because that file sits ~375 lines PAST the 1500 cap so every line there is one unit. Paid down rather than baselined, and the move was the coherent unit rather than the minimum one: BOTH refusals went, the new backward half and the pre-existing forward half (assert_scheduled_deprecations_clear), into _lib/release_migration_gate.ts at 184 lines and therefore UNDER the cap, so the pair and all their rationale now cost nothing. They moved on merit rather than only on arithmetic -- they are the two halves of one obligation, written eleven months apart, and release.ts held only the two call sites. parse_version stayed module-private in release.ts and the lib carries a two-line _minor_patch instead: exporting a private helper to serve one caller would widen the surface of the file the move exists to narrow. release.ts 1,875 -> 1,733: a branch that ADDED a pipeline refusal leaves the file eighty-one lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports nothing staged and nothing untracked at this commit, so a clean CI checkout measures the same 17,866. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises -- which is how CI found it: the gate exited 0 with a loose-ratchet warning and the test went red. PRIOR ENTRY: Lowered 17,959 -> 17,947 on 2026-09-11 by the findings-ledger branch, on this entry's own doctrine. The branch adds step 7 to release.ts, which sits ~326 lines PAST the 1500 cap so every line there is one unit, and it came in at +145. Paid down rather than baselined, in two moves. `settle_findings_ledger` and `_blocking_without_disposition` moved out of release.ts into _lib/release_findings_ingest.ts -- 95 lines, and that module is under the cap, so the step and its rationale now cost nothing. It moved on merit rather than only on arithmetic: the module already owns every message the step prints and every argv it builds, and release.ts held only the sequencing. Then the `--ci` fallback dispatch of the three tag-triggered workflows -- 24 lines of loop and warning with no reader elsewhere in step 10 -- moved into _lib/release_tag_dispatch.ts, also under the cap. release.ts 1,826 -> 1,814: a branch that ADDED a pipeline step leaves the file twelve lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ file staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,947. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,963 -> 17,959 on 2026-09-09 by feat/cdd-fidelity-council, on the same shape as the entry below and with the same discriminator. The branch's src-link rewrite (a blind review found 253 of 268 links under dist/agent-src/guidelines/ dead, because condense.ts folded only the docs/ prefixes and never (../)+src/rules|skills) came in at +15 excess: condense.ts sits ~1,208 lines PAST the 1500 cap, so every line there is one unit. Paid down rather than baselined, in the way this entry's doctrine prescribes. `_rewrite_body_links` and its two regex constants moved out of condense.ts into _lib/guidelines_lane.ts, 151 lines and therefore UNDER the cap, so the function and its prose now cost nothing. It moved on merit rather than only on arithmetic: every rule the rewriter applies is a statement about which source tree projects where, which is that module's own subject, and condense.ts held it only because that is where the projector lives. condense.ts 2,712 -> 2,708 net, after the one import line and the one call-site rename -- a branch that ADDED a rewrite rule leaves the file four lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ files tracked and nothing untracked, so a clean CI checkout of this commit measures the same 17,959. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,973 -> 17,963 on 2026-09-08 by drain/graph-shipped-close. The branch registers five code-graph MCP tools (road-to-a-graph-that-is-shipped 4.1). Their five records and schemas are ~250 lines, and putting them in mcp_server/tools.ts -- which sits ~500 lines PAST the 1500 cap, so every line there is one unit -- would have cost ~250 excess. They live in mcp_server/graph_tools.ts instead (~280 lines, UNDER the cap, so they and their prose cost nothing), and tools.ts spreads them into ALLOWLIST in two lines: one import and one `...GRAPH_TOOLS,`. Those two were paid for rather than baselined, in the way this entry's doctrine prescribes: `_strip` and `_resolvePath` -- a whitespace trim and a tolerant realpath, generic by nature -- moved out of tools.ts into mcp_server/path_util.ts, also under the cap. They are imported under their original underscore names, so all 28 call sites are unchanged and a two-function move does not read as a sweep. tools.ts 2,025 -> 2,015: -12 from the extraction, +2 from the registration, net -10 for a branch that ADDED a feature. CORRECTED 2026-09-08 after an independent review checked the figure against the tree -- this sentence read '2,025 -> 2,013, net -12, against the +2 the registration needed', which states an intermediate file length as the final one and leaves the arithmetic (-12) and the conclusion (-10) describing different trees. `git show origin/main:...tools.ts | wc -l` is 2025 and the working tree is 2015. The TOTAL, 17,963, was always the gate's own output and is unchanged. Every other file this branch touches or creates -- code_graph/verbs.ts, code_graph/cli.ts, code_graph/build.ts, code_graph/detect.ts, code_graph/query.ts, code_graph/sqlite_store.ts, code_graph/types.ts, _lib/regression_neighbourhood.ts -- is under the 1500 ceiling before and after, so it contributes zero excess whatever it grew by. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,963. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,974 -> 17,973 on 2026-09-08 by drain/topology-c1. The branch adds a live-path emit to council_cli.ts, which sits 2,454 lines PAST the 1500 cap so every line there is one unit, and paid its own way down rather than raising the baseline, in the way this entry's doctrine prescribes. The twelve-line `all_responses` assembly (a spread, three conditionals and a push) moved out of council_cli.ts into ai_council/deliberation_metrics.ts::runCallsFrom, 353 lines and therefore UNDER the cap, so the six stage labels and their prose cost nothing. It moved on merit rather than only on arithmetic: 'which calls did this run make, and at which stage' is that module's own subject, and the CLI held the list only as a flat array with the stage boundaries implicit in the order -- both readings now come out of one walk, so the billing total and the attribution can never be computed over different sets. council_cli.ts 3,955 -> 3,954 net, after the two call lines, the import and the one payload key the feature needed. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,973. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,016 -> 17,974 on 2026-09-07 by fix/single-delivery-unconditional. SETTLED FIGURE, and it supersedes an intra-session 17,962 this same branch committed earlier — read the direction against MAIN, which is what the ratchet protects: main is 18,016, the branch leaves 17,974, net -42. The 17,962 was this branch's own low before a neutral review returned twelve findings; fixing them added a real mechanism to mcp_server and condense.ts (the flat-wrapper carriage gate the review showed was missing, plus its four-skip predicate), and condense.ts sits ~1,215 lines PAST the cap so each of those lines is one unit. Paid down first, in the way this entry's doctrine prescribes: _suggestSkillForTaskHandler and its 18-line docstring moved out of mcp_server/tools.ts (2,079 -> 2,025) into mcp_server/suggest_skill.ts, 72 lines and UNDER the cap, so its prose costs nothing. The residual +12 against the intra-session low is the gate's own output on the settled tree and is recorded rather than engineered away, because the alternative was extracting _nested_command_subpath and its two callers out of condense.ts - which needs MODULE_STATE, _relativeToPosix and _domains_command_logical passed in, a wider diff than the finding warrants and one no review asked for. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the three new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,974. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-07, 18,061/18,017 -> 18,016. drain/admissible-council-seats and fix/release-obligation-answerable each lowered from the SAME 18,062 base in parallel — main to 18,061 (net -1: curlJsonPost, the seat-status helpers and the per-seat config parsing moved out of the three over-ceiling council files) and the branch to 18,017 (net -45: the /dev/tty prompt helpers moved out of release.ts into _lib/tty_prompt.ts, 76 lines and UNDER the cap, taking release.ts 1871 -> 1826). Taking either side alone is wrong in a different direction, which is the reconciliation doctrine this entry already carried from 2026-09-03: main's value silently discards the branch's earned -45, and the branch's value RAISES the baseline against main and weakens the gate. The committed number is neither — it is the gate's own output on the MERGED tree, where both reductions apply, and it equals the arithmetic (18,062 - 45 - 1 = 18,016) rather than being reconciled by it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports ZERO untracked files, so a clean CI checkout of this commit measures the same 18,016. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in the merge commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,062 -> 18,061 on 2026-09-07 by drain/admissible-council-seats. The branch's own additions to the three over-ceiling files (ai_council/config.ts, council_cli.ts, ai_council/clients.ts) came in at +96 excess and were paid down to -1 rather than baselined, in the four ways this entry's doctrine prescribes: `curlJsonPost` moved out of clients.ts into ai_council/api_transport.ts (UNDER the cap, so the prose and the three new provider shims cost nothing); the seat-status helpers moved out of council_cli.ts into ai_council/status_surface.ts, taking an orphaned doc comment with them; the three new per-seat config fields' parsing moved out of config.ts into ai_council/seat_policy.ts::parseSeatFields; and three prose blocks that the branch's own transport repair made FACTUALLY FALSE (the `openai` / `google-genai` Python-SDK claims, and a `_curlJsonPost` pointer to a function that had moved) were corrected and shortened in the same change. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports zero untracked files with the five new src/ files staged, so a clean CI checkout of this commit measures the same 18,061. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried here because tests/scripts/check_source_size_budget.test.ts:166 asserts baseline == live and therefore blocks where the gate only advises -- the lowering commit must carry its own baseline update. Lowered 18,068 -> 18,062 on 2026-09-06 by drain/host-enforcement-truth. Collapsing the five per-host binding constants in install.ts into src/scripts/hooks/host_lowering.yaml removed 29 lines from a file ~3,900 past the 1500 cap, where every line costs one excess; the journal's surface column and its extracted migration helper gave 23 back. Lowered 18,245 -> 18,230 on 2026-09-02 by drain/publication-integrity-option-a. Phase 2 Option A moved the authoring instruction out of the generator: release.ts, which sits ~530 lines PAST the 1500 cap so every line there costs one excess, loses the comment emission, a 16-line HEAD_DEFAULT doc block and its alias const, and gains a shorter writer docstring. The doc block moved to _lib/release_material.ts, which is 289 lines and therefore UNDER the cap, so the same prose now costs nothing. Net -15. The branch first came in at +8 and paid its own way down rather than raising the baseline. BRANCH-SIDE ENTRY: Lowered 17,947 -> 17,944 on 2026-09-13 by drain/decision-closure, on this entry's own doctrine and at the gate's own request. The branch's ownership-axis additions to ai_council/config.ts came in at +86 excess: that file sits ~700 lines PAST the 1500 cap, so every line there is one unit. Paid down rather than baselined, in one move. The eight ownership class names, the two Iron-Law sets, the merged default-mode map and the mode-check function moved out of config.ts into ai_council/ownership_classes.ts -- 91 lines, UNDER the cap, so the vocabulary and its prose now cost nothing. It moved on merit rather than only on arithmetic: the roadmap-side gate lint_decision_classes needs the same eight names and has no business importing the council's whole schema to learn them, and the loader now carries three lines where it carried twenty-four. config.ts 2,182 -> 2,179: a branch that ADDED an entire decision axis leaves the file three lines shorter than it found it. Every other src/ file this branch creates -- lint_decision_classes.ts, lint_roadmap_producers.ts, closure_scan.ts, council_record_shape.ts, scope_growth.ts, ownership_classes.ts -- is under the 1500 ceiling, so it contributes zero excess whatever it grew by. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ files tracked and nothing untracked, so a clean CI checkout of this commit measures the same 17,944. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,959 -> 17,947 on 2026-09-11 by the findings-ledger branch, on this entry's own doctrine. The branch adds step 7 to release.ts, which sits ~326 lines PAST the 1500 cap so every line there is one unit, and it came in at +145. Paid down rather than baselined, in two moves. `settle_findings_ledger` and `_blocking_without_disposition` moved out of release.ts into _lib/release_findings_ingest.ts -- 95 lines, and that module is under the cap, so the step and its rationale now cost nothing. It moved on merit rather than only on arithmetic: the module already owns every message the step prints and every argv it builds, and release.ts held only the sequencing. Then the `--ci` fallback dispatch of the three tag-triggered workflows -- 24 lines of loop and warning with no reader elsewhere in step 10 -- moved into _lib/release_tag_dispatch.ts, also under the cap. release.ts 1,826 -> 1,814: a branch that ADDED a pipeline step leaves the file twelve lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ file staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,947. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,963 -> 17,959 on 2026-09-09 by feat/cdd-fidelity-council, on the same shape as the entry below and with the same discriminator. The branch's src-link rewrite (a blind review found 253 of 268 links under dist/agent-src/guidelines/ dead, because condense.ts folded only the docs/ prefixes and never (../)+src/rules|skills) came in at +15 excess: condense.ts sits ~1,208 lines PAST the 1500 cap, so every line there is one unit. Paid down rather than baselined, in the way this entry's doctrine prescribes. `_rewrite_body_links` and its two regex constants moved out of condense.ts into _lib/guidelines_lane.ts, 151 lines and therefore UNDER the cap, so the function and its prose now cost nothing. It moved on merit rather than only on arithmetic: every rule the rewriter applies is a statement about which source tree projects where, which is that module's own subject, and condense.ts held it only because that is where the projector lives. condense.ts 2,712 -> 2,708 net, after the one import line and the one call-site rename -- a branch that ADDED a rewrite rule leaves the file four lines shorter than it found it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the branch's new src/ files tracked and nothing untracked, so a clean CI checkout of this commit measures the same 17,959. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,973 -> 17,963 on 2026-09-08 by drain/graph-shipped-close. The branch registers five code-graph MCP tools (road-to-a-graph-that-is-shipped 4.1). Their five records and schemas are ~250 lines, and putting them in mcp_server/tools.ts -- which sits ~500 lines PAST the 1500 cap, so every line there is one unit -- would have cost ~250 excess. They live in mcp_server/graph_tools.ts instead (~280 lines, UNDER the cap, so they and their prose cost nothing), and tools.ts spreads them into ALLOWLIST in two lines: one import and one `...GRAPH_TOOLS,`. Those two were paid for rather than baselined, in the way this entry's doctrine prescribes: `_strip` and `_resolvePath` -- a whitespace trim and a tolerant realpath, generic by nature -- moved out of tools.ts into mcp_server/path_util.ts, also under the cap. They are imported under their original underscore names, so all 28 call sites are unchanged and a two-function move does not read as a sweep. tools.ts 2,025 -> 2,015: -12 from the extraction, +2 from the registration, net -10 for a branch that ADDED a feature. CORRECTED 2026-09-08 after an independent review checked the figure against the tree -- this sentence read '2,025 -> 2,013, net -12, against the +2 the registration needed', which states an intermediate file length as the final one and leaves the arithmetic (-12) and the conclusion (-10) describing different trees. `git show origin/main:...tools.ts | wc -l` is 2025 and the working tree is 2015. The TOTAL, 17,963, was always the gate's own output and is unchanged. Every other file this branch touches or creates -- code_graph/verbs.ts, code_graph/cli.ts, code_graph/build.ts, code_graph/detect.ts, code_graph/query.ts, code_graph/sqlite_store.ts, code_graph/types.ts, _lib/regression_neighbourhood.ts -- is under the 1500 ceiling before and after, so it contributes zero excess whatever it grew by. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,963. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 17,974 -> 17,973 on 2026-09-08 by drain/topology-c1. The branch adds a live-path emit to council_cli.ts, which sits 2,454 lines PAST the 1500 cap so every line there is one unit, and paid its own way down rather than raising the baseline, in the way this entry's doctrine prescribes. The twelve-line `all_responses` assembly (a spread, three conditionals and a push) moved out of council_cli.ts into ai_council/deliberation_metrics.ts::runCallsFrom, 353 lines and therefore UNDER the cap, so the six stage labels and their prose cost nothing. It moved on merit rather than only on arithmetic: 'which calls did this run make, and at which stage' is that module's own subject, and the CLI held the list only as a flat array with the stage boundaries implicit in the order -- both readings now come out of one walk, so the billing total and the attribution can never be computed over different sets. council_cli.ts 3,955 -> 3,954 net, after the two call lines, the import and the one payload key the feature needed. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the two new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,973. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,016 -> 17,974 on 2026-09-07 by fix/single-delivery-unconditional. SETTLED FIGURE, and it supersedes an intra-session 17,962 this same branch committed earlier — read the direction against MAIN, which is what the ratchet protects: main is 18,016, the branch leaves 17,974, net -42. The 17,962 was this branch's own low before a neutral review returned twelve findings; fixing them added a real mechanism to mcp_server and condense.ts (the flat-wrapper carriage gate the review showed was missing, plus its four-skip predicate), and condense.ts sits ~1,215 lines PAST the cap so each of those lines is one unit. Paid down first, in the way this entry's doctrine prescribes: _suggestSkillForTaskHandler and its 18-line docstring moved out of mcp_server/tools.ts (2,079 -> 2,025) into mcp_server/suggest_skill.ts, 72 lines and UNDER the cap, so its prose costs nothing. The residual +12 against the intra-session low is the gate's own output on the settled tree and is recorded rather than engineered away, because the alternative was extracting _nested_command_subpath and its two callers out of condense.ts - which needs MODULE_STATE, _relativeToPosix and _domains_command_logical passed in, a wider diff than the finding warrants and one no review asked for. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports the three new src/ files staged and nothing untracked, so a clean CI checkout of this commit measures the same 17,974. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in this commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: MERGE RECONCILIATION 2026-09-07, 18,061/18,017 -> 18,016. drain/admissible-council-seats and fix/release-obligation-answerable each lowered from the SAME 18,062 base in parallel — main to 18,061 (net -1: curlJsonPost, the seat-status helpers and the per-seat config parsing moved out of the three over-ceiling council files) and the branch to 18,017 (net -45: the /dev/tty prompt helpers moved out of release.ts into _lib/tty_prompt.ts, 76 lines and UNDER the cap, taking release.ts 1871 -> 1826). Taking either side alone is wrong in a different direction, which is the reconciliation doctrine this entry already carried from 2026-09-03: main's value silently discards the branch's earned -45, and the branch's value RAISES the baseline against main and weakens the gate. The committed number is neither — it is the gate's own output on the MERGED tree, where both reductions apply, and it equals the arithmetic (18,062 - 45 - 1 = 18,016) rather than being reconciled by it. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports ZERO untracked files, so a clean CI checkout of this commit measures the same 18,016. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried in the merge commit because tests/scripts/check_source_size_budget.test.ts asserts baseline == live and therefore BLOCKS where the gate only advises. PRIOR ENTRY: Lowered 18,062 -> 18,061 on 2026-09-07 by drain/admissible-council-seats. The branch's own additions to the three over-ceiling files (ai_council/config.ts, council_cli.ts, ai_council/clients.ts) came in at +96 excess and were paid down to -1 rather than baselined, in the four ways this entry's doctrine prescribes: `curlJsonPost` moved out of clients.ts into ai_council/api_transport.ts (UNDER the cap, so the prose and the three new provider shims cost nothing); the seat-status helpers moved out of council_cli.ts into ai_council/status_surface.ts, taking an orphaned doc comment with them; the three new per-seat config fields' parsing moved out of config.ts into ai_council/seat_policy.ts::parseSeatFields; and three prose blocks that the branch's own transport repair made FACTUALLY FALSE (the `openai` / `google-genai` Python-SDK claims, and a `_curlJsonPost` pointer to a function that had moved) were corrected and shortened in the same change. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the 1500-line ceiling, and `git status --porcelain -uall -- src/` reports zero untracked files with the five new src/ files staged, so a clean CI checkout of this commit measures the same 18,061. If CI reads anything else, CI's number is the correct one and this note is the record of why. Carried here because tests/scripts/check_source_size_budget.test.ts:166 asserts baseline == live and therefore blocks where the gate only advises -- the lowering commit must carry its own baseline update. Lowered 18,068 -> 18,062 on 2026-09-06 by drain/host-enforcement-truth. Collapsing the five per-host binding constants in install.ts into src/scripts/hooks/host_lowering.yaml removed 29 lines from a file ~3,900 past the 1500 cap, where every line costs one excess; the journal's surface column and its extracted migration helper gave 23 back. Lowered 18,245 -> 18,230 on 2026-09-02 by drain/publication-integrity-option-a. Phase 2 Option A moved the authoring instruction out of the generator: release.ts, which sits ~530 lines PAST the 1500 cap so every line there costs one excess, loses the comment emission, a 16-line HEAD_DEFAULT doc block and its alias const, and gains a shorter writer docstring. The doc block moved to _lib/release_material.ts, which is 289 lines and therefore UNDER the cap, so the same prose now costs nothing. Net -15. The branch first came in at +8 and paid its own way down rather than raising the baseline.",
50
+ "reason": "Lowered 17,585 -> 17,571 on 2026-10-05 by lane/installed-layer-thinned, and the gate asked for it BY NAME. The gain is this branch's own, through two extractions rather than a sweep: `_resolve_global_rule_scope` to `src/install/globalRuleScope.ts` and the thinning mechanism to `src/scripts/_lib/thin_rules.ts`. PRIOR REASON: Lowered 17,590 -> 17,585 on 2026-10-03 by drain/rule-carrier-phase1b-20261002, and the gate asked for it BY NAME: it reported `ratchet is loose` and named 17,585. The gain is INCIDENTAL rather than sought, and it comes from two files that sit past the 1500-line cap. `src/scripts/ai_council/clients.ts` (2,852 lines, 1,352 past) lost the 18-line doc comment and declaration of `OPENAI_CLI_VENDOR_DEFAULT`, which moved to a new `ai_council/vendor_defaults.ts` well under the cap, so those lines stopped being charged; the move itself was made to break an import edge costing 51,523 B of composed hook bundle, not to shed lines. `src/scripts/install.ts` (5,229 lines, 3,729 past) gained a three-line call site for the headless `.gitignore` block and NOT the 44-line function behind it, which was written into `_lib/gitignore_block.ts` instead — that placement was chosen when this gate reported +44 and said a ratchet only turns one way, and it is the better home anyway. Net across both: -5. LOCAL READING, on the same discriminator the entries above use: the gate walks authored source under src/, and a porcelain status over that root reports no untracked files, so a clean CI checkout of this commit measures the same 17,585. `landed` is refreshed deliberately — checkRatchet returns `improved` BEFORE it evaluates staleness, so an entry left at 17,590 while the tree measures 17,585 would never expire at any age. PRIOR ENTRY: Lowered 17,592 -> 17,590 on 2026-10-03 by drain/rule-carrier-phase1-20261002, and the gain was INCIDENTAL rather than sought. The branch replaced `condense.ts::_lean_projection_settings` — an eight-line private reader of `lean_projection.mode` and `.hosts` — with one call to the shared `resolveLeanProjection`, net -2 lines in a file that sits ~1,195 lines PAST the 1500 cap, so every line removed there is one excess removed. Nothing was deleted to make a number: the projector reads the same settings file it always read, and `task sync` plus `task generate-tools` produce zero changes under `dist/agent-src/`, which is how that roadmap's risk 2 (one mode resolver moves the projector) was discharged. The gate reported the tree at 17,590 against a baseline of 17,592 and asked for exactly this lowering, so the gain cannot be silently given back. LOCAL READING, ADMISSIBLE ON THE SAME DISCRIMINATOR THIS FILE'S OTHER ENTRIES USE: the gate walks `src/` only, and a porcelain status over that root reported no untracked files, so a clean CI checkout of this commit measures the same 17,590. If CI reads anything else, CI's number is the correct one and this note is the record of why. PRIOR ENTRY: Lowered 18,230 -> 18,209 on 2026-09-03 by drain/artifact-location. `doctor --strict` needed 16 lines of integration wiring in cmd_doctor.ts, which sits ~2,100 lines PAST the 1500 cap so every line there costs one excess. The branch first came in at +137 and paid its own way down rather than raising the baseline: the strict semantics, threshold, kill switch, payload helper and argv fragments moved to _cli/_doctor_strict.ts (~160 lines, under the cap, costs nothing), taking it to +15; then the 37-line drift renderer moved to _cli/_doctor_emit.ts. Net -21. The renderer was chosen deliberately: pure rendering, two dependencies, no argparse involvement and therefore none of the byte-parity risk the parser surface carries against the retired Python implementation; nothing outside cmd_doctor.ts imported it. An AI council on the residual split (a: raise by 15 / d: descope the feature); neither was taken, because a parallel branch demonstrated the same day that paying down is achievable in this codebase, which is the evidence the split lacked. This gate's own test comment prescribes it: a commit that splits a god-file lowers the excess and must carry the lowered baseline. MERGE RECONCILIATION 2026-09-03, 18,209 -> 18,205: drain/wired-instruments and drain/artifact-location each lowered from the SAME 18,230 base in parallel -- the branch to 18,226 (net -4, run_continuation_hook.ts's termination ladder moved to _lib/continuation_ladder.ts and runtime_journal.ts's prose to _lib/outcome_vocabularies.ts, both under the cap) and main to 18,209 (net -21, the doctor --strict split above). Taking either side alone is wrong in a different direction: main's value silently discards the branch's earned -4, and the branch's value RAISES the baseline against main and weakens the gate. The committed number is neither -- it is the gate's own output on the merged tree, where both reductions apply. THIS LOCAL READING IS ADMISSIBLE HERE, and the discriminator matters because this file's ci-parity:local-only entry records a 165 -> 164 lowering that was reverted for exactly the opposite case: that count depends on how the environment resolves the projection surface, whereas this gate walks only SOURCE_ROOTS = ['src'] (check_source_size_budget.ts:88) counting excess lines over the 1500 ceiling, and `git status --porcelain -uall -- src/` reported ZERO untracked files, so a clean CI checkout of this commit measures the same 18,205. If CI reads anything else, CI's number is the correct one and this note is the record of why. LOWERED 18,205 -> 18,193 on 2026-09-03 by fix/release-curation-ask. The change adds a fifth publication guard, and its own additions landed at +10 excess: release.ts 2,008 -> 2,018, every line of which is past the 1500 cap. Paid down rather than baselined, in the two ways this gate's doctrine prescribes. The guard's rationale (~13 lines of docstring, including why prMerged is a parameter rather than a call-site if) lives in release_publication.ts, 915 lines and therefore UNDER the cap, so the prose costs nothing; and the two pure text helpers _splitlines and _rstrip moved out of release.ts into release_env.ts (333 lines, also under the cap), taking release.ts to 1,996 -- 12 BELOW where it started. The branch came in at +10 and leaves at -12. Recorded while moving them: _splitlines is duplicated a third and fourth time at adoption_report.ts:106 and readme_linter.ts:418; collapsing all three onto one definition touches three modules and was left out of this change rather than done silently. LOWERED 18,193 -> 18,180 on 2026-09-03 by fix/release-branch-reuse. The step-1 branch decision -- twenty lines of if/else in release.ts -- became one call to checkout_release_branch in release_publication.ts, which is 1,019 lines and therefore UNDER the 1500 cap, so the twenty lines plus a ~35-line rationale now cost nothing. release.ts 1,996 -> 1,983, every one of those lines being past the cap. The drill grew 765 -> 918 for two new scenarios and the snapshot/restore that keeps them from writing the real CHANGELOG, and it is under the cap too. A change that adds a feature and lowers the excess is the shape this gate's doctrine asks for; the alternative was a +13 raise for logic that had no business in the god-file. LOWERED 18,180 -> 18,068 on 2026-09-05 by fix/release-gate-producer-parity. The change wires the governance-mix obligation into the writer and the two local guards and adds a release-gate locality registry; its own additions to release.ts landed at +19 excess, every one of those lines past the 1500 cap. Paid down rather than baselined, in the way this entry's doctrine prescribes: the 132-line test-count-trend unit (_TEST_COUNT_LINE_RE, _TEST_LIST_MAX_BUFFER, _count_from_list_result, _count_tests_current, _previous_test_count_from_changelog, _render_test_trend_line) moved from release.ts into release_publication.ts, which is under the cap and where it now belongs on merit rather than only on arithmetic -- the same diff makes the missing `Tests: N` footer a section-level publication blocker, so the writer that emits the footer and the guard that refuses its absence sit in one module. release.ts 1,983 -> 1,871. All four names are re-exported from release.ts, so tests/scripts/release.test.ts is unchanged. LOCAL READING, ADMISSIBLE ON THIS ENTRY'S OWN DISCRIMINATOR: the gate walks only SOURCE_ROOTS=['src'] counting excess over the ceiling, and `git status --porcelain -uall -- src/` reports ZERO untracked files with the two new src/ files staged, so a clean CI checkout of this commit measures the same 18,068. If CI reads anything else, CI's number is the correct one and this note is the record of why."
41
51
  },
42
52
  "ci-parity:local-only": {
43
53
  "count": 165,
@@ -48,6 +58,10 @@
48
58
  "gate-self-test:registered-non-adopters": {
49
59
  "count": 24,
50
60
  "landed": "2026-08-06",
61
+ "reaffirmed": {
62
+ "date": "2026-10-02",
63
+ "reason": "Re-derived today against the live manifest: still 24 of 32 registered-enforced gates carrying neither a `--self-test` nor a `// self-test-exempt:` marker. The count has not drifted in either direction, so nothing accumulated behind the baseline and no gate quietly lost its proof. NOT CLEARED, and the reason is the migration mechanism this entry's own note fixes rather than any lack of attention: adopters are added alongside a real change to that gate, never in a sweep, because a self-test written by someone not touching the gate proves the author's reading of it and not the gate. Eight gates have adopted on exactly those terms. Driving the remaining 24 to zero inside an unrelated PR would be the sweep the note rules out, and it would produce 24 self-tests nobody had a reason to think hard about. HONEST LIMIT of this reaffirmation: it asserts the population was re-counted, not that each of the 24 was re-read. Re-reading 24 gates is the work the next 56 days are for, at the rate the mechanism prescribes — roughly one per gate touched. Revisit-if: the count rises, or a release needs the floor cleared. Expires 2026-11-27 (56 days); a second reaffirmation at an unchanged 24 would be the suppression this clause exists to catch, so the next one is owed adopters instead."
64
+ },
51
65
  "note": "Self-test adoption ratchet, expressed as a shrink-only NON-adopter count. 24 of the 32 gates registered enforced in gate-coverage.yml carry neither a `--self-test` (`_lib/gate_self_test.ts`) nor a `// self-test-exempt: <reason>` marker, so nothing proves they DISCRIMINATE — an enforced `scanned:` floor proves a gate read something, only a self-test proves the reading changes the verdict. Deliberately NOT an adoption column ratcheted upward: check_gate_coverage.ts's own report_hardening_ratchet rejects that shape in this same file (\"grades the solution instead of the problem\"), and the sibling adoption ratchet (check_gate_completeness) is already a non-adopter count. Population is the manifest, not every script under src/scripts: padding the manifest to move this number would mean adding a floor per row. Shrink-only from here — a NEW registered gate must adopt or exempt. Migration mechanism, same as the ledger ratchet above: gates adopt as they are touched, not in a sweep — the eight current adopters were each added alongside a real change to that gate. The 56-day non-stagnation clause applies unchanged, so a count parked here fails on its own.",
52
66
  "falsifier": "./scripts-run src/scripts/check_gate_coverage"
53
67
  },
@@ -67,9 +81,9 @@
67
81
  "note": "All 18 are `handoff_tier_mismatch`: a senior-tier skill links to a peer whose frontmatter carries no `tier` (reported as tier='unset') — e.g. build-buy-partner → adr-create, customer-research → po-discovery, gated-reach → threat-modeling. This is a tier-metadata backfill backlog on the LINKED-TO skills, not a broken link. The one genuinely dangling link revealed by the same repair (competitive-positioning → a non-existent ../analyze-reference-repo/SKILL.md; it is a command, not a skill) was FIXED in the repairing commit rather than baselined. Clearing this entry means backfilling `tier` on the linked-to skills, or deciding that `tier: unset` on a link target is not a violation and narrowing the rule."
68
82
  },
69
83
  "lint_pack_boundaries": {
70
- "count": 337,
71
- "landed": "2026-08-02",
72
- "note": "Markdown links between source artefacts that cross a pack boundary the source pack's `requires` graph does not reach — revealed when the scan root moved off the deleted packages/ tree to the live corpus (0 -> 753 artefacts scanned). 82 distinct pack pairs across 131 source files; largest single class is engineering-base -> meta (73), skills in a consumer-installable pack citing this package's own maintenance skills. Each is a link that dangles for a consumer who installs the source pack without the target's. Judged real drift rather than an over-strict gate because it is long-tailed — top bucket 22%, no single systematic cause — unlike the lint_artefact_frontmatter case, where one required shape had 0-of-288 adoption. Fix per finding: add the edge to packs.yml requires, retarget the link, or move the artefact."
84
+ "count": 120,
85
+ "landed": "2026-10-09",
86
+ "note": "Markdown links between source artefacts that cross a pack boundary the source pack's `requires` graph does not reach — revealed when the scan root moved off the deleted packages/ tree to the live corpus (0 -> 753 artefacts scanned). Each is a link that dangles for a consumer who installs the source pack without the target's. Judged real drift rather than an over-strict gate because it is long-tailed — no single systematic cause — unlike the lint_artefact_frontmatter case, where one required shape had 0-of-288 adoption. Fix per finding: add the edge to packs.yml requires, retarget the link, or move the artefact; where none of the three fits because the edge would run from a base pack into a narrower one, drop the link and keep the artefact name as prose. 2026-10-01, 337 -> 203 and `landed` refreshed: the gate's largest recorded class (engineering-base -> meta, 73 at the time) was never drift. `meta` is `always_on: true`, which `config/packs.resolve_active_packs` seeds into every projection before expanding any selection, so a link into it cannot dangle and the premise above does not hold for it. The allow rule now reads `core` plus every always-on pack rather than the hard-coded `core` alone — one-way, a link OUT of an always-on pack is still reported. That removed 141 of 379; a further 35 occurrences were de-linked at source, clearing every link added since the 2026-08-02 baseline. Delta, per-link introducing commits and the five readings: agents/evidence/analysis/pack-boundary-delta-2026-10-01.md. KNOWN LIMITATION, named rather than left behind the numeric drop (council review 2026-10-01, the reviewer's highest-leverage ask): for a link that runs from a BASE pack into a NARROWER one — engineering-base -> react, meta -> git, frontend-design -> brand — none of the three fixes above is available, and that is a mismatch between this gate's rule and the pack schema rather than a backlog. `requires` is the only edge type the resolver expands, and it is transitive and install-forcing, so declaring base -> narrow would push the narrow pack into every install of the base; `suggests` is advisory and this gate does not read it. Retargeting needs an in-pack equivalent that does not exist, and moving the artefact changes which install ships it. So the cross-reference is dropped and the artefact named in prose, which is why a reader will find named-but-unlinked siblings in these files. Closing the mismatch properly needs a schema decision — an advisory edge this gate reads, or an exemption for base packs — and that is a product call, not cleanup. 2026-10-01 -> 2026-10-09, 203 -> 120: the KNOWN LIMITATION named above is closed rather than carried. D5 of road-to-gates-a-pull-request-can-hear (AI council 2026-10-07, anthropic + openai, 2/2, $0.00; adopted 2026-10-08 under the owner's delegation of council-decidable questions) chose option (a): `suggests` in packs.yml is an advisory, non-installing, ONE-HOP, ONE-WAY edge that this gate now reads as permitting a link. It is never expanded transitively — that would give it the install-forcing reach `requires` has, which is the property the decision depends on it not having. 83 links are permitted by it, and the split is MEASURED rather than enumerated by hand — an earlier revision of this note enumerated it and got both halves wrong, which is why the number below is the gate's own output. 73 sit on edges this change ADDED: engineering-base -> laravel 31, -> frontend-design 12, -> symfony 4, -> php 4, -> nextjs 4, -> react 2, -> brand 2, -> product-basic 1; the multi-pack source engineering-base+frontend-design -> brand 3 and -> frontend-design 2; frontend-design -> brand 3; finance-basic -> finance-advanced 4; scale-discipline -> history-discipline 1. The other 10 sit on `suggests` edges that ALREADY EXISTED and that the gate simply did not read: laravel -> frontend-design 3, product-basic -> product-discovery 3, brand -> ai-image 2, react -> frontend-design 1, frontend-design -> react 1. Reverting only this change's packs.yml additions therefore yields 193, not 203 — measured, not derived; 203 returns only if the gate also stops reading `suggests` at all. `--show-permitted` lists them with the permitting edge named, so an advisory permit is visible rather than silent. THE CONDITION THE COUNCIL ATTACHED WAS MET BEFORE THE DROP: all 203 links were classified documentation-reference / optional-integration / load-bearing, and only safely-degrading ones are permitted. 4 of 203 (2.0%) are load-bearing, under the >20% figure one seat named as the abort threshold. That figure is the THIRD reading: a second pass said 3.0%, and an independent adversarial review found its line attribution wrong — the locator gave every repeated occurrence of a link the FIRST match's line and basis, so 34 rows cited a sentence that was not theirs. Re-located per occurrence, one of the six fell away under the page's own rule. Every correction has moved the number down, which is worth stating plainly rather than treating as reassurance. 2 of the 4 sat on a now-permitted edge (corpus-grounding, tailwind-engineer) and were remediated BEFORE the edge was declared, so no permitted link is load-bearing as it stands: corpus-grounding gained an engine-scoped ATTRIBUTION.md beside the code the MIT notice covers, because that engine ships in engineering-base while the corpus ships in frontend-design, and tailwind-engineer now states that without frontend-design its rule is checked by reading rather than by a linter. The classification table marks both rows `load-bearing (remediated)` with the basis, so the evidence and the claim agree. The other 2 are NOT permitted and remain inside the 120. KNOWN BLIND SPOT, measured on 2026-10-09 rather than reasoned about: a link planted on a pack pair joined by an advisory edge leaves the count at 120 and exits 0 at any headroom — the permit is per EDGE, so the ratchet cannot see it. The permitted COUNT therefore prints on every run including `--quiet` (the planted link moved it 83 -> 84), which is the only standing signal that the set is growing. There is no ratchet on it. A link on an UNDECLARED pair still reads 121 and exits 1, measured the same day. Per-link table, both classifier readings and the sampling error rate: agents/evidence/analysis/pack-boundary-link-classification-2026-10-09.md."
73
87
  },
74
88
  "lint_provenance_vocabulary:permanence-language": {
75
89
  "count": 5,
@@ -78,10 +92,14 @@
78
92
  "falsifier": "./scripts-run src/scripts/lint_provenance_vocabulary"
79
93
  },
80
94
  "lint_settings_classes:derivable-surface": {
81
- "count": 83,
82
- "landed": "2026-08-12",
83
- "note": "Anti-regrowth ratchet for the settings disposition axis. 83 of 134 template leaves are classified `derivable` — the mechanism can decide from the situation, so the key should not exist — and each names the replacement that would decide instead (`lint_settings_classes` rejects the bare label, which is what keeps the class from becoming a synonym for \"inconvenient to keep\"). This is a DELETION QUEUE, not 83 deletions: a row stays until the mechanism it names actually exists, and deleting a key ahead of its mechanism is a silently-changed default rather than a simplification. Shrink-only from here, which is the anti-regrowth half — a NEW key classified `derivable` raises the number and reds, so a key whose answer the situation already carries cannot be added at all. The 56-day non-stagnation clause is the other half and is wanted here rather than tolerated: a queue that never drains is a stated direction nobody is walking. The queue opened at 88 of 140 on 2026-08-12 and drained to 83 of 134 the same day: six keys had no reader whatsoever (telegraph.speak_scope, chat_history.max_size_kb, chat_history.on_overflow, quality.wait_for_remote_ci, screenshots.data_bearing_gate, legal_review_prep.consented_at), five of them `derivable` and one a `consent` row reclassified because a published-egress confirmation is a Hard Floor no setting may lift. An unread key is the only deletion that cannot silently change a default, which is why that batch went first. The classification itself is docs/contracts/settings-classes.md.",
84
- "falsifier": "./scripts-run src/scripts/lint_settings_classes"
95
+ "count": 37,
96
+ "landed": "2026-10-09",
97
+ "note": "Anti-regrowth ratchet for the settings disposition axis. 83 of 134 template leaves are classified `derivable` — the mechanism can decide from the situation, so the key should not exist — and each names the replacement that would decide instead (`lint_settings_classes` rejects the bare label, which is what keeps the class from becoming a synonym for \"inconvenient to keep\"). This is a DELETION QUEUE, not 83 deletions: a row stays until the mechanism it names actually exists, and deleting a key ahead of its mechanism is a silently-changed default rather than a simplification. Shrink-only from here, which is the anti-regrowth half — a NEW key classified `derivable` raises the number and reds, so a key whose answer the situation already carries cannot be added at all. The 56-day non-stagnation clause is the other half and is wanted here rather than tolerated: a queue that never drains is a stated direction nobody is walking. The queue opened at 88 of 140 on 2026-08-12 and drained to 83 of 134 the same day: six keys had no reader whatsoever (telegraph.speak_scope, chat_history.max_size_kb, chat_history.on_overflow, quality.wait_for_remote_ci, screenshots.data_bearing_gate, legal_review_prep.consented_at), five of them `derivable` and one a `consent` row reclassified because a published-egress confirmation is a Hard Floor no setting may lift. An unread key is the only deletion that cannot silently change a default, which is why that batch went first. The classification itself is docs/contracts/settings-classes.md. DRAIN 2026-10-09, 83 -> 74 (road-to-settings-classes-derivable-surface-stagnation step 2.1): the nine output-and-tone keys (personal.minimal_output, personal.play_by_play, personal.pr_comment_bot_icon, the four verbosity leaves preview_artifacts / routine_confirmations / post_action_reports / intent_announcements, telegraph.speak, tokens.rich_skills) were retired with every reader rewritten to the old default, each registered in REMOVED_KEYS (src/scripts/_lib/settings_removed_keys.ts) so a leftover value warns once and is ignored. DRAIN 2026-10-09, 74 -> 64 (step 2.2): reasoning.auto_gate and the nine reasoning.components.* switches retired; rdp-gate.md's task and host signals decide per component, reasoning.enabled stays the hard off. DRAIN 2026-10-09, 64 -> 62 (step 2.3): roadmap.skip_pre_run_gate and roadmap.dashboard_regen_cadence retired; roadmap.quality_cadence moved back to the queue because it has two defaults (template per_phase, reader fallback end_of_roadmap). DRAIN 2026-10-09, 62 -> 54 (step 2.4): commands.auto_detect, the four commands.suggestion knobs (enabled, confidence_floor, cooldown_seconds, max_options) and commands.create_pr.api_examples / ui_paths / api_paths retired; the suggester loader now reads only blocklist. DRAIN 2026-10-09, 54 -> 47 (step 2.5): memory.cadence, memory.review_threshold and the five knowledge.global_sharing redaction / promotion / freshness leaves retired; load_global_sharing_config now merges only enabled and allowed_tiers, and the hook settings loader no longer reads memory.cadence. DRAIN 2026-10-09, 47 -> 42 (step 2.6): hooks.concern_budget.max_per_event / hard_fail, decision_engine.surface_traces / on_block_fallback and explain.enable_last retired; the decision_engine parser still accepts the two engine keys so a leftover does not reject the whole block. DRAIN 2026-10-09, 42 -> 37 (step 2.7): project.pr_template, pipelines.skill_improvement, consistency.cross_source, subagents.downshift and ai_team.suppress_setup_hint retired; the ai_team loader accepts the last one as a deleted key so the template's leftover line never fails /team. Phase 2 retired 46 of the 47 selected keys; roadmap.quality_cadence stayed in the queue because it has two defaults.",
98
+ "falsifier": "./scripts-run src/scripts/lint_settings_classes",
99
+ "reaffirmed": {
100
+ "date": "2026-10-09",
101
+ "reason": "Re-read all 83 rows today rather than re-stamping the date, and the re-reading is why the count did not move: not one of the 83 keys is drainable, and the reason is the same in every case. Method, because the obvious one is wrong here. A grep for the dotted literal suggested about 25 keys with zero or near-zero hits. Every one of those 25 was then checked against its owning module individually, and every one had a real reader. The literal grep misses them because TypeScript consumers read nested settings by object access (settings.hard_fail, this._settings.on_block_fallback) rather than restating the path, and because rule, context and command consumers name the key only in prose (\"Read `X` from `.agent-settings.yml`\"). A zero from the dotted grep is a property of the grep, not of the tree. The root cause, stated once: in every one of the 83 rows the named replacement mechanism WAS built, and the old key was never retired from its original consumer. The replacement is additive, not substitutive. Two shapes. Real code still reads it - decision_engine.* is a complete wired gate across work_engine/scoring/decision_engine.ts and hooks/builtin/decision_gate.ts; hooks.concern_budget.hard_fail is read by lint_hook_concern_budget.ts:235 through its own YAML walker; commands.suggestion.* is wired through four files under command_suggester/. Or an instruction-only artefact still says to read it - the nine reasoning.* rows are named explicitly as Signal 1 in rdp-gate.md, in the same file whose Signals 2 and 3 are the cited replacement. One row is a different case and is recorded so nobody re-derives it: hooks.code_graph.enabled genuinely has no code reader, but docs/MIGRATION.md carries an explicit compatibility commitment to keep the surface registered and disabled. Deleting it would break a stated promise rather than a default. The precedent this is measured against: the queue opened at 88 on 2026-08-12 and drained to 83 the same day, taking exactly the six keys that had no reader anywhere. An unread key is the only deletion that cannot silently change a default. Re-run today, the remaining 83 contain no new unread key. What would actually lower this number is therefore not a cleanup but a decision: retire one side of a coexisting old/new mechanism pair, which is a behaviour change. The largest coherent group is the nine reasoning.* rows, all in rdp-gate.md, where the replacement signals demonstrably already run beside the setting. That is the owner call and is not taken here. Reaffirmed on the owner word after the drain was attempted and yielded zero, with the per-key evidence produced first. The clause asks for a re-read and got one; it did not get a date."
102
+ }
85
103
  },
86
104
  "check_no_external_sources:shape-block": {
87
105
  "count": 148,
@@ -95,16 +113,46 @@
95
113
  "note": "243 pre-contract usages of `[~]` in archived roadmaps that carry no `deferred-resolution:` annotation. The annotation contract was settled by council on 2026-08-27; every file in this population predates it, the oldest by months (agents/roadmaps/archive/step-99-north-star-restructure.md:92 is 2026-05 and uses the glyph to mean 'partially green, not a regression'). They are NOT repaired: rewriting an archived roadmap's step semantics retroactively invents an intent nobody recorded, and the honest alternative glyph `[-]` is owner-reserved (archive_completed_roadmaps.ts:396). Shrink-only from here, one owner decision at a time. This ratchet covers ONLY the unannotated class; the broken-destination class -- a receiver deleted, renamed, re-parented, skipped, or archived with open steps -- is a hard failure at zero with no baseline, because deleting agents/roadmaps/road-to-council-topology-evidence-followups.md produces 38 of those and must red immediately rather than nudge a count. REMEDY WHEN THE 56-DAY NON-STAGNATION CLAUSE FIRES (from `landed`, i.e. 2026-10-28), named here because neither remedy the checker prints fits this population: \"fix the findings\" is ruled out by the sentence above -- rewriting an archived roadmap's step semantics retroactively invents an intent nobody recorded -- and \"lower the count\" is ruled out with it, since this population only shrinks when an owner decides one entry at a time. The remedy that fits is a `reaffirmed: {date, reason}` block on THIS entry (`_lib/gate_baseline.ts`), whose reason lands in the diff of the change that makes it: that is the path for debt which is genuinely unrepairable rather than merely unattended. A reaffirmation is not automatic. It asserts that the 243 were re-read and are still unrepairable, and if any of them has become repairable in the meantime the count goes down instead. Do not reaffirm at age 0 -- the clause exists so the question is asked once every 56 days, and answering it early answers nothing. RENAMED from `lint_carrier_integrity` to `lint_deferral_integrity` by ADR-262, which deleted the `status: carrier` frontmatter value; the count was deliberately NOT re-measured, because a rename is not a measurement and lowering a ratchet on one would be laundering."
96
114
  },
97
115
  "lint_roadmap_later_disposition:review-by": {
98
- "count": 68,
99
- "landed": "2026-09-07",
116
+ "count": 66,
117
+ "landed": "2026-10-02",
100
118
  "falsifier": "./scripts-run src/scripts/lint_roadmap_later_disposition # the ratchet line names the current count; it fails when the count RISES above this entry",
101
119
  "note": "Parked roadmaps under agents/roadmaps/later/ carrying no `review_by:` in their frontmatter. NOT a dead-scan-root repair — the obligation is NEW (road-to-observed-learning-signal step 3.4), so every pre-existing parked roadmap lacks it by construction and 68 of 82 is the count at introduction rather than revealed debt. A hard-zero gate was refused on this repository's own recorded ground: a gate that fails its own tree on 68 files the landing change did not cause is reverted rather than adopted. Shrink-only from here, which is the property that matters: a NEWLY parked roadmap must carry `review_by` or this reds immediately. Clearing an entry is one roadmap at a time — read what the park is waiting on, pick a date a human would actually honour, and lower the count. The figure is the gate's own output on this branch (`--json`, class `review-by`), and the same 68 was measured independently over a tree that had grown by one file since the roadmap's own pin, which is why the roadmap's stated floor and this entry agree."
102
120
  },
103
121
  "lint_roadmap_later_disposition:wake-condition": {
104
- "count": 18,
105
- "landed": "2026-09-07",
122
+ "count": 17,
123
+ "landed": "2026-10-09",
106
124
  "falsifier": "./scripts-run src/scripts/lint_roadmap_later_disposition # the ratchet line names the current count; it fails when the count RISES above this entry",
107
- "note": "Parked roadmaps carrying no machine-readable wake condition — neither a structured three-part `entry_condition` (what / when / who) nor one of the four unambiguous body phrases. REVEALED rather than created: until 2026-09-07 the gate short-circuited on the frontmatter status word (`if (status !== 'later' && !RESUME_RE.test(body))`), so 63 of 82 parked roadmaps passed with no resume text present at all, and `trigger` was in RESUME_RE so 11 more passed on a prose mention of the word. Measured after the correction and after migrating the three pre-contract scalar `entry_condition` fields to the mapping form: 19 before the migration, 18 after. Shrink-only from here: a NEWLY parked roadmap must carry a real wake condition. A malformed `entry_condition` is deliberately OUTSIDE this ratchet and fails hard at zero — a scalar or a blank part is a defect the author introduced in the change that wrote it, not inherited debt."
125
+ "note": "Parked roadmaps carrying no machine-readable wake condition — neither a structured three-part `entry_condition` (what / when / who) nor one of the four unambiguous body phrases. REVEALED rather than created: until 2026-09-07 the gate short-circuited on the frontmatter status word (`if (status !== 'later' && !RESUME_RE.test(body))`), so 63 of 82 parked roadmaps passed with no resume text present at all, and `trigger` was in RESUME_RE so 11 more passed on a prose mention of the word. Measured after the correction and after migrating the three pre-contract scalar `entry_condition` fields to the mapping form: 19 before the migration, 18 after. Shrink-only from here: a NEWLY parked roadmap must carry a real wake condition. A malformed `entry_condition` is deliberately OUTSIDE this ratchet and fails hard at zero — a scalar or a blank part is a defect the author introduced in the change that wrote it, not inherited debt. 2026-10-09, 18 -> 17: `road-to-a-graph-that-feeds-the-gate` was parked with a STRUCTURED `entry_condition` (what / when / who), so it joins the compliant set rather than the baselined one. Its wake condition is a non-zero positive stratum in the pre-registered corpus — re-measured 2026-10-09 and still 0 on all three arms, which is why the park is an accrual wait and not a deferral."
126
+ },
127
+ "report_installed_rule_links:kinds:claude-code:rules": {
128
+ "count": 114,
129
+ "landed": "2026-10-06",
130
+ "falsifier": "./scripts-run src/scripts/report_installed_rule_links --kinds all --host claude-code # the `kind: rules` line prints the live count and this entry as its baseline",
131
+ "note": "Links inside installed Claude Code rules that point at nothing the install carries, counted per kind for the first time on 2026-10-06 — a starting point, not a regression. 114 rather than the rule reading's 115 because the per-kind split moves the one `docs/` target into the non-projected row. REPORT-ONLY: nothing fails on this number yet (road-to-installed-links-of-every-kind D2); whether a kind count should ever fail a build is decided after one release of readings. Shrink-only: lower it when a repair lands; repairs belong to road-to-rule-triggers-and-links-that-hold."
132
+ },
133
+ "report_installed_rule_links:kinds:claude-code:skills": {
134
+ "count": 296,
135
+ "landed": "2026-10-06",
136
+ "falsifier": "./scripts-run src/scripts/report_installed_rule_links --kinds all --host claude-code # the `kind: skills` line prints the live count and this entry as its baseline",
137
+ "note": "Links inside installed Claude Code skills (every `.md` under a skill, resolved from its own installed directory) that point at nothing the install carries, of 1752 deployable links, counted for the first time on 2026-10-06 — a starting point, not a regression. `docs/` and ADR targets are excluded and live in the non-projected entry. REPORT-ONLY (road-to-installed-links-of-every-kind D2). Shrink-only: lower it when a repair lands."
138
+ },
139
+ "report_installed_rule_links:kinds:claude-code:commands": {
140
+ "count": 441,
141
+ "landed": "2026-10-06",
142
+ "falsifier": "./scripts-run src/scripts/report_installed_rule_links --kinds all --host claude-code # the `kind: commands` line prints the live count and this entry as its baseline",
143
+ "note": "Links inside installed Claude Code commands that point at nothing the install carries, of 891 deployable links, counted for the first time on 2026-10-06 — a starting point, not a regression. `docs/` and ADR targets are excluded and live in the non-projected entry. REPORT-ONLY (road-to-installed-links-of-every-kind D2). Shrink-only: lower it when a repair lands."
144
+ },
145
+ "report_installed_rule_links:kinds:claude-code:non-projected": {
146
+ "count": 314,
147
+ "landed": "2026-10-06",
148
+ "falsifier": "./scripts-run src/scripts/report_installed_rule_links --kinds all --host claude-code # the `kind: non-projected` line prints the live count and this entry as its baseline",
149
+ "note": "Links from installed Claude Code rules, skills and commands into `docs/` or an ADR file — trees no install carries, so every one is dead by construction and is kept apart from the deployable counts. Counted for the first time on 2026-10-06. REPORT-ONLY (road-to-installed-links-of-every-kind D2). Shrink-only: a link removed or replaced by an installed target lowers it."
150
+ },
151
+ "report_installed_rule_links:kinds:augment:contexts": {
152
+ "count": 107,
153
+ "landed": "2026-10-06",
154
+ "falsifier": "./scripts-run src/scripts/report_installed_rule_links --kinds all --host augment # the `kind: contexts` line prints the live count and this entry as its baseline",
155
+ "note": "Links inside installed contexts that point at nothing the install carries, of 447 deployable links. Recorded for augment because it is the only host whose plan deploys `contexts/`; Claude Code's reading for the kind is `not installed`, which is an absence, not a zero. Counted for the first time on 2026-10-06. REPORT-ONLY (road-to-installed-links-of-every-kind D2). Shrink-only: lower it when a repair lands."
108
156
  }
109
157
  },
110
158
  "retired": {
@@ -171,3 +171,22 @@
171
171
  # Written by POST /api/v1/wizard/state between step transitions, deleted
172
172
  # on POST /api/v1/wizard/finish. Local-only crash-recovery aid.
173
173
  /.agent-config/wizard-state.json
174
+
175
+ # Agent config — neighbour-census caches, written by `agent-config doctor
176
+ # neighbours` into the otherwise-TRACKED `agents/reports/` directory. Named
177
+ # here because that placement is what makes them a leak rather than a nuisance:
178
+ # every other file in that directory is a committed report, so a broad staging
179
+ # of the directory is the normal thing to do and would publish
180
+ #
181
+ # · each neighbour skill's ABSOLUTE source path, which is rooted at the
182
+ # consumer's home directory and therefore carries their account name
183
+ # (`/Users/<name>/.claude/skills/...`), and
184
+ # · the consumer's full installed-skill inventory with per-file digests.
185
+ #
186
+ # Both are derived and disposable: rollback is `rm`, and the next
187
+ # `doctor neighbours` run rebuilds them from the census digest. Neither has
188
+ # ever been tracked in this repository or shipped in a release, so this entry
189
+ # ignores them going forward and unstages nothing — see this file's header on
190
+ # why an entry here is never a tracked -> untracked transition.
191
+ /agents/reports/neighbour-overlap.json
192
+ /agents/reports/neighbour-scan.json
@@ -0,0 +1,25 @@
1
+ {
2
+ "_comment": "Byte ceiling and parser cap for the self-hosted hook bundle (dist/hooks/dispatch.js). Registered by road-to-a-hook-bundle-with-one-yaml-reader step 2.1. Read by src/scripts/check_hook_bundle_composition.ts, which builds the bundle from source with --metafile and compares. WHY A CEILING AT ALL: every concern is inlined into one bundle that every hook event loads, so a dependency added for one concern is paid by all of them, on every dispatch. The second YAML parser that opened this roadmap cost 95,846 bytes and reached a release as a review finding rather than as a red check. A ceiling makes the next one a red check.",
3
+ "schema_version": 1,
4
+ "registered_at": "2026-10-01",
5
+ "owner": "maintainer",
6
+ "review_by": "2027-10-01",
7
+ "max_bytes": 1550000,
8
+ "max_bytes_derivation": "Measured 1,514,715 bytes on origin/main at 213d87055 (the gate's own reading, APFS-cloned node_modules so no worktree path artefacts). The ceiling is that reading plus ~2.3 % of headroom, rounded to 1,550,000, on the same doctrine as the 2026-10-01 registration: a bundle is rebuilt from source on every run, so an esbuild minor that renames symbols moves the figure by hundreds of bytes with no change to this tree, and a ceiling one byte above the reading would red on that. Composition is healthy at this reading and was checked rather than assumed: one YAML package (258,833 bytes) and 1,238,525 bytes of own source, so the growth is own code, not a re-entered dependency. The 1,564,211-byte pre-swap regression this roadmap closed still cannot reappear under it.",
9
+ "shrink_only": true,
10
+ "shrink_only_note": "A RAISE needs a recorded reason in `raise_log` below naming what was added and why it could not be avoided. Enforced since road-to-a-ratification-fence-that-follows-its-imports 3.2: the gate reads `max_bytes` at the base revision, and a working value above it fails unless `raise_log` gained an entry whose `to` equals the new value. A lowering needs no entry. This file is also on the ratification gate's watched set, so a raise carries a record as well as a log entry.",
11
+ "raise_log": [
12
+ {
13
+ "date": "2026-10-01",
14
+ "from": 1500000,
15
+ "to": 1550000,
16
+ "by": "agent, during the inbox-2026-10 drain",
17
+ "what_was_added": "Nothing in this commit. The 1,500,000 ceiling was red on the very commit that registered it: measured 1,511,489 bytes at 22b19e520, which is the merge of the PR that introduced the budget. Its derivation read 1,469,738 bytes on the PR branch, whose base predated three PRs that had merged meanwhile — the failure-event binding of #2160 (sixteen concerns on a new slot), the touched-file quality pass of #2152, and the evidence classification of #2153 — and #2162 landed after it. The gate ran on each PR's pre-merge tree and never on the merge result, so every one of those PRs was green alone and the trunk was red the moment they were together.",
18
+ "why_it_could_not_be_avoided": "The bytes are deliberately merged capability, not an accident to trim: the composition check above shows one parser and no duplicate dependency, so there is nothing to remove that would not remove a feature. The alternative — reverting a merged lane to fit a ceiling derived against a base that no longer exists — would discard working code to satisfy a number that never described this tree.",
19
+ "what_would_have_caught_it": "Measuring the ceiling against the merge result rather than the PR branch. A ceiling derived on a branch is a statement about that branch; the trunk is what the gate defends, and the two diverge exactly when several lanes land in one day."
20
+ }
21
+ ],
22
+ "max_yaml_packages": 1,
23
+ "max_yaml_packages_note": "The dispatch path reads YAML for the hook manifest, the host-lowering table and the settings contract. One reader covers all three. Two cost 95,846 bytes for a single call site and were invisible until an external rescore counted them — which is why this is a cap rather than prose. The package set the cap counts over is YAML_PACKAGES in the gate.",
24
+ "what_this_does_not_bound": "Latency. A smaller bundle is not a measured speed-up; src/config/hook-latency-budget.json owns the wall-clock axis and is not derived from this file. Nor does it bound dist/install/install.mjs or dist/mcp/server.mjs, which carry their own module graphs."
25
+ }
@@ -33,7 +33,12 @@
33
33
  "skill-route": 512,
34
34
  "skill-route_reason": "road-to-inbox-harvest-2026-08-d-runtime-skill-routing 2.1: one line carrying at most three skill ids and their scores - pointers, never bodies. Registered BELOW the 1024 default deliberately: this row is the ceiling that keeps it a pointer line, so a later change that starts injecting descriptions fails the build instead of quietly doubling a per-turn slot that already carries nine other concerns under a 4096-byte sum cap",
35
35
  "rule-inject": 16384,
36
- "rule-inject_reason": "LOWERED 20480 -> 16384 on 2026-09-08, R2 finding 3. THE OLD PAIR WAS TWO STATISTICS IN TWO UNITS, not one decision: this row and `hooks/rule_inject_hook.ts::CAP_BYTES` carried the p90 of the matched-body TOKEN distribution rounded to 500 tok and converted at ~4 B/tok (5,000 tok -> 20,480 B), while `per_slot_sum_caps_bytes.user_prompt_submit` carries the p90 gate-open FIRE SIZE in bytes rounded up to 512 (16,384 B) \u2014 the activation charge owner ruling E2 specifies for the flipping run. One concern licensed 25% above the whole slot's registered sum, on a slot carrying 12 other concerns, made the overrun DESIGNED IN: measured max fire was 20,406 B and 38 of 330 corpus fires exceeded 16,384 B. Reconciled DOWNWARD, never by raising the slot: the charge is the owner-specified number and the concern now conforms to it instead of exceeding it. MEASURED COST of the lowering, over the frozen `tests/eval/routing-matrix` corpus with the command path included (330 fires): p90 16,865 -> 14,507 B, max 20,406 -> 16,348 B, fires truncated 33 -> 45, rule bodies dropped to fit the cap 63 -> 88. So 25 further bodies are withheld on the top-decile fires, where five or more rules matched at once \u2014 a delivery reduction, stated rather than implied, and the endpoints do not measure it (`b-recall` scores `matchTierRules`, not `selectForInjection`). WHAT ENFORCES WHAT, because the finding correctly asked: `CAP_BYTES` is enforced at emission by `selectForInjection`, which drops whole bodies to stay under it, so a fire is TRUNCATED and never over-emitted. The per-slot sums here are an AUTHORING-time control read by `bench_hook_injection`; the only runtime enforcement is `per_turn_aggregate_bytes.ceiling_bytes` in `hooks/injection_budget.ts`, which drops lowest-severity advisories and does not read a per-slot row. And the bench cannot see a real fire from this concern at all: it runs each concern under AGENT_CONFIG_REPLAY=1, which re-imposes the settings gate, and this repository carries no `.agent-settings.yml`, so the concern measures 0 B there. The CROSS-CONCERN residue is therefore still unbounded by any acting gate \u2014 it is now bounded in the authoring record rather than guaranteed to breach, which is a smaller claim than closure and is the honest one."
36
+ "rule-inject_reason": "RESTATED IN CHARACTERS 2026-10-03 by road-to-a-rule-carrier-that-works-outside-the-repo step 1.5: the number below is unchanged and is no longer the bound that binds at emission \u2014 `per_concern_caps_chars.rule-inject` is, at 8,000 characters, and this row is now the outer envelope the selection stays inside. The byte row is kept rather than converted because it is what `selectForInjection` enforces and what the offline model prices against, and the two readers must keep seeing one number. Its own history follows. LOWERED 20480 -> 16384 on 2026-09-08, R2 finding 3. THE OLD PAIR WAS TWO STATISTICS IN TWO UNITS, not one decision: this row and `hooks/rule_inject_hook.ts::CAP_BYTES` carried the p90 of the matched-body TOKEN distribution rounded to 500 tok and converted at ~4 B/tok (5,000 tok -> 20,480 B), while `per_slot_sum_caps_bytes.user_prompt_submit` carries the p90 gate-open FIRE SIZE in bytes rounded up to 512 (16,384 B) \u2014 the activation charge owner ruling E2 specifies for the flipping run. One concern licensed 25% above the whole slot's registered sum, on a slot carrying 12 other concerns, made the overrun DESIGNED IN: measured max fire was 20,406 B and 38 of 330 corpus fires exceeded 16,384 B. Reconciled DOWNWARD, never by raising the slot: the charge is the owner-specified number and the concern now conforms to it instead of exceeding it. MEASURED COST of the lowering, over the frozen `tests/eval/routing-matrix` corpus with the command path included (330 fires): p90 16,865 -> 14,507 B, max 20,406 -> 16,348 B, fires truncated 33 -> 45, rule bodies dropped to fit the cap 63 -> 88. So 25 further bodies are withheld on the top-decile fires, where five or more rules matched at once \u2014 a delivery reduction, stated rather than implied, and the endpoints do not measure it (`b-recall` scores `matchTierRules`, not `selectForInjection`). WHAT ENFORCES WHAT, because the finding correctly asked: `CAP_BYTES` is enforced at emission by `selectForInjection`, which drops whole bodies to stay under it, so a fire is TRUNCATED and never over-emitted. The per-slot sums here are an AUTHORING-time control read by `bench_hook_injection`; the only runtime enforcement is `per_turn_aggregate_bytes.ceiling_bytes` in `hooks/injection_budget.ts`, which drops lowest-severity advisories and does not read a per-slot row. And the bench cannot see a real fire from this concern at all: it runs each concern under AGENT_CONFIG_REPLAY=1, which re-imposes the settings gate, and this repository carries no `.agent-settings.yml`, so the concern measures 0 B there. The CROSS-CONCERN residue is therefore still unbounded by any acting gate \u2014 it is now bounded in the authoring record rather than guaranteed to breach, which is a smaller claim than closure and is the honest one."
37
+ },
38
+ "per_concern_caps_chars": {
39
+ "_comment": "A SECOND UNIT, for the one concern whose host threshold is stated in characters rather than bytes. Claude Code replaces an `additionalContext` longer than 10,000 CHARACTERS with a path and a 2,000-character preview, so a delivery over that line is not truncated \u2014 it is substituted, and the obligation text never arrives at all. A byte row cannot express that bound without a bytes-per-character ratio that drifts with the corpus, so the character budget is registered in its own unit instead of converted into the bytes map above. Absent concern = no character cap; the bytes row still applies to every concern.",
40
+ "rule-inject": 8000,
41
+ "rule-inject_reason": "road-to-a-rule-carrier-that-works-outside-the-repo step 1.5, decision D2: 8,000 characters on the WHOLE rule-produced string, framing and manifest included, because that is what the host measures. WHICH STRING IT BOUNDS, separated here because the two readings give different margins and D2's own wording did not: this number bounds the RULE-PRODUCED string, the `<rule>` elements plus the manifest. The host's 10,000 applies to the `additionalContext` it assembles, and the other concerns on this slot measured 1,272 characters of non-rule text, so the margin is 2,000 if the host measures this concern's payload alone and 728 if it measures the assembled string. 8,000 is safe under both; which reading is right is not established here and the smaller number is the one to plan against. Raised as a finding by the openai seat of the 2026-10-03 ratification council. ENFORCED AT EMISSION by `hooks/rule_inject_hook.ts::compose`, which reserves the manifest's worst-case length before admitting any text and then demotes a full body to its law, or reports it as `omitted_budget`, rather than truncating \u2014 half an obligation reads like a whole one. THE TWO UNITS CANNOT BREACH EACH OTHER at any ratio this corpus produces, and the ratio is measured rather than assumed: over the 121 projected rule files the mean is 1.0088 bytes per character and the per-file maximum is 1.0346 (`no-decorative-emojis-in-git-surfaces.md`), so 8,000 characters is at most 8,277 bytes against the 16,384-byte row above. A composed string would have to average 2.05 bytes per character to reach that row, which no Markdown rule corpus produces \u2014 but that is EVIDENCE OVER ONE CORPUS AND NOT AN INVARIANT, so `compose` enforces this byte row at emission as well, independently of the character budget. A 6,000-character payload of three-byte code points is 18,000 bytes, under the character budget and over this row, and a fixture emits exactly that and asserts it is reported rather than sent. Raised as a finding by the openai seat of the 2026-10-03 ratification council. `tests/scripts/rule_inject_hook.test.ts` pins both the constant and the measured ratio, so a corpus that did start producing such a string fails a test rather than silently substituting a path for the obligation."
37
42
  },
38
43
  "per_slot_sum_caps_bytes": {
39
44
  "_comment": "Cross-concern per-fire sum per slot (roadmap 3.1). session_start is one-time and may carry the restore payloads; per-turn slots stay tight.",
@@ -0,0 +1,33 @@
1
+ {
2
+ "_comment": "Per-host PUBLISHED instruction-budget limit, against which the installed-layer report measures what a consumer actually loads. road-to-an-installed-layer-that-is-thinned steps 1.4 and 3.5. Loader and the 80 % warning fraction: src/scripts/_lib/installed_layer.ts. A host with no limit this tree can cite carries `limit: null`, which renders as `no published limit` and fires NO warning — an absent limit is an absent measurement, never a pass. NOTHING HERE MAY BE INVENTED: every non-null `limit` carries a `source` naming where the figure is recorded, and `kind` says what sort of record that is. `vendor-published` means a figure this tree read from the host's own published material; `reported` means a figure recorded in this repository from an observation, which is weaker and is marked so a later reader does not promote it by mistake.",
3
+ "claude-code": {
4
+ "limit": 150000,
5
+ "kind": "reported",
6
+ "source": "agents/roadmaps/road-to-an-installed-layer-that-is-thinned.md:7 (`estate_offset_exempt`), and the same figure in the `Source:` header of that file and of road-to-a-rule-carrier-that-works-outside-the-repo and road-to-rule-triggers-and-links-that-hold. All three cite round `inbox-2026-10-c`, which reproduced the host's notice on a fresh install at 102 unconditional files / 338,225 characters.",
7
+ "note": "MARKED `reported`, NOT `vendor-published`, DELIBERATELY. The round that carries the primary record lived under `agents/tmp.old/inbox-2026-10-c/` and has since been pruned, so what this tree can still show is three roadmap headers citing it and not the notice itself. That is enough to record the figure and not enough to call it read from the host. Checked 2026-10-05: `ls agents/tmp.old/inbox-2026-10-c/` reports no such directory. Promote to `vendor-published` only against the host's own published material, never against another copy of this entry."
8
+ },
9
+ "cursor": {
10
+ "limit": null,
11
+ "kind": "unpublished",
12
+ "source": null,
13
+ "note": "No instruction-budget limit for this host is recorded anywhere in this tree. `null` is the honest reading and is NOT a statement that the host has no limit — only that this repository has never written one down."
14
+ },
15
+ "augment": {
16
+ "limit": null,
17
+ "kind": "unpublished",
18
+ "source": null,
19
+ "note": "No instruction-budget limit for this host is recorded anywhere in this tree."
20
+ },
21
+ "windsurf": {
22
+ "limit": null,
23
+ "kind": "unpublished",
24
+ "source": null,
25
+ "note": "No instruction-budget limit for this host is recorded anywhere in this tree."
26
+ },
27
+ "cline": {
28
+ "limit": null,
29
+ "kind": "unpublished",
30
+ "source": null,
31
+ "note": "No instruction-budget limit for this host is recorded anywhere in this tree."
32
+ }
33
+ }
@@ -55,7 +55,8 @@ workflow: .github/workflows/release-validation.yml
55
55
 
56
56
  jobs:
57
57
  release-shape:
58
- local: 'git diff --name-only origin/main...HEAD | ./scripts-run src/scripts/check_release_pr_shape --files -'
58
+ # Two steps in one job: the file-name shape, then the manifest content.
59
+ local: 'git diff --name-only origin/main...HEAD | ./scripts-run src/scripts/check_release_pr_shape --files - && ./scripts-run src/scripts/check_release_manifest_content --base origin/main'
59
60
  verify: true
60
61
  # The assertion is about a RELEASE PR's diff — every ordinary branch fails
61
62
  # it by construction, so running it off a release branch would teach a