@event4u/agent-config 16.3.0 → 16.5.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 (532) 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 +178 -78
  5. package/README.md +2 -2
  6. package/agents/templates/.ai-council.yml.example +26 -8
  7. package/dist/agent-src/commands/analyze/inbox.md +10 -7
  8. package/dist/agent-src/commands/bug/investigate.md +1 -1
  9. package/dist/agent-src/commands/commit/in-chunks.md +40 -31
  10. package/dist/agent-src/commands/commit.md +72 -33
  11. package/dist/agent-src/commands/condense.md +2 -8
  12. package/dist/agent-src/commands/council/debate.md +11 -7
  13. package/dist/agent-src/commands/council/default.md +10 -9
  14. package/dist/agent-src/commands/council.md +1 -1
  15. package/dist/agent-src/commands/design.md +1 -1
  16. package/dist/agent-src/commands/estimate-ticket.md +1 -1
  17. package/dist/agent-src/commands/feature/explore.md +3 -3
  18. package/dist/agent-src/commands/feature/plan.md +1 -1
  19. package/dist/agent-src/commands/fix/ci.md +17 -3
  20. package/dist/agent-src/commands/fix/commit-messages.md +48 -23
  21. package/dist/agent-src/commands/fix/pr-comments.md +3 -6
  22. package/dist/agent-src/commands/implement-ticket.md +3 -3
  23. package/dist/agent-src/commands/memory/add.md +4 -16
  24. package/dist/agent-src/commands/memory/load.md +5 -6
  25. package/dist/agent-src/commands/memory/promote.md +3 -16
  26. package/dist/agent-src/commands/mission/upgrade.md +3 -2
  27. package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
  28. package/dist/agent-src/commands/optimize/deep.md +4 -2
  29. package/dist/agent-src/commands/optimize/rtk.md +4 -26
  30. package/dist/agent-src/commands/pr/create/description-only.md +18 -15
  31. package/dist/agent-src/commands/pr/create.md +42 -34
  32. package/dist/agent-src/commands/pr/merge.md +136 -9
  33. package/dist/agent-src/commands/prepare-for-review.md +13 -11
  34. package/dist/agent-src/commands/project/analyze.md +7 -35
  35. package/dist/agent-src/commands/refine-ticket.md +1 -1
  36. package/dist/agent-src/commands/review/changes.md +14 -19
  37. package/dist/agent-src/commands/roadmap/next.md +10 -1
  38. package/dist/agent-src/commands/roadmap/process-full.md +52 -38
  39. package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
  40. package/dist/agent-src/commands/worktree/create.md +7 -3
  41. package/dist/agent-src/commands/worktree/verify.md +2 -1
  42. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
  43. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
  44. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
  45. package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
  46. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
  47. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
  48. package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
  49. package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
  50. package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
  51. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
  52. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
  53. package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
  54. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
  55. package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
  56. package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
  57. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  58. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  59. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  60. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  61. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  62. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
  63. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  64. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  65. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
  66. package/dist/agent-src/guidelines/design-antipatterns.md +1 -1
  67. package/dist/agent-src/guidelines/php/git.md +15 -2
  68. package/dist/agent-src/rules/active-remediation.md +0 -1
  69. package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
  70. package/dist/agent-src/rules/architecture.md +0 -1
  71. package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
  72. package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
  73. package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
  74. package/dist/agent-src/rules/autonomous-execution.md +0 -1
  75. package/dist/agent-src/rules/brand-consistency.md +0 -1
  76. package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
  77. package/dist/agent-src/rules/broken-access-control.md +0 -1
  78. package/dist/agent-src/rules/cli-output-handling.md +0 -1
  79. package/dist/agent-src/rules/code-comment-discipline.md +0 -1
  80. package/dist/agent-src/rules/code-provenance.md +0 -1
  81. package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
  82. package/dist/agent-src/rules/commit-conventions.md +1 -2
  83. package/dist/agent-src/rules/communication-through-line.md +1 -2
  84. package/dist/agent-src/rules/content-quoting-floor.md +1 -2
  85. package/dist/agent-src/rules/context-hygiene.md +5 -5
  86. package/dist/agent-src/rules/copilot-routing.md +1 -2
  87. package/dist/agent-src/rules/council-availability.md +4 -4
  88. package/dist/agent-src/rules/cross-source-consistency.md +4 -6
  89. package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
  90. package/dist/agent-src/rules/delegation-policy.md +2 -3
  91. package/dist/agent-src/rules/design-fidelity.md +0 -1
  92. package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
  93. package/dist/agent-src/rules/devcontainer-routing.md +1 -2
  94. package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
  95. package/dist/agent-src/rules/docker-commands.md +0 -1
  96. package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
  97. package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
  98. package/dist/agent-src/rules/domain-safety-pii.md +0 -1
  99. package/dist/agent-src/rules/domain-safety-retention.md +0 -1
  100. package/dist/agent-src/rules/downstream-changes.md +0 -1
  101. package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
  102. package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
  103. package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
  104. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
  105. package/dist/agent-src/rules/finance-safety-floor.md +0 -1
  106. package/dist/agent-src/rules/fix-what-you-see.md +6 -32
  107. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
  108. package/dist/agent-src/rules/git-history-discipline.md +1 -2
  109. package/dist/agent-src/rules/guidelines.md +0 -1
  110. package/dist/agent-src/rules/history-discipline.md +0 -1
  111. package/dist/agent-src/rules/icon-consistency.md +0 -1
  112. package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
  113. package/dist/agent-src/rules/improve-before-implement.md +0 -1
  114. package/dist/agent-src/rules/invite-challenge.md +0 -1
  115. package/dist/agent-src/rules/laravel-routing.md +1 -2
  116. package/dist/agent-src/rules/laravel-translations.md +0 -1
  117. package/dist/agent-src/rules/legal-safety-floor.md +0 -1
  118. package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
  119. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
  120. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
  121. package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
  122. package/dist/agent-src/rules/media-governance-routing.md +1 -2
  123. package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
  124. package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
  125. package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
  126. package/dist/agent-src/rules/missing-tool-handling.md +0 -1
  127. package/dist/agent-src/rules/model-recommendation.md +0 -1
  128. package/dist/agent-src/rules/neighbour-precedence.md +64 -0
  129. package/dist/agent-src/rules/no-attribution-footers.md +0 -1
  130. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
  131. package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
  132. package/dist/agent-src/rules/no-roadmap-references.md +0 -1
  133. package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
  134. package/dist/agent-src/rules/onboarding-gate.md +0 -1
  135. package/dist/agent-src/rules/output-discipline.md +0 -1
  136. package/dist/agent-src/rules/package-ci-checks.md +0 -1
  137. package/dist/agent-src/rules/persona-governance.md +2 -3
  138. package/dist/agent-src/rules/php-coding.md +0 -1
  139. package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
  140. package/dist/agent-src/rules/preservation-guard.md +0 -1
  141. package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
  142. package/dist/agent-src/rules/question-not-instruction.md +0 -1
  143. package/dist/agent-src/rules/reviewer-awareness.md +0 -1
  144. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
  145. package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
  146. package/dist/agent-src/rules/role-mode-adherence.md +0 -1
  147. package/dist/agent-src/rules/rule-type-governance.md +0 -1
  148. package/dist/agent-src/rules/runtime-safety.md +0 -1
  149. package/dist/agent-src/rules/scale-discipline.md +0 -1
  150. package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
  151. package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
  152. package/dist/agent-src/rules/self-repair-loop.md +0 -1
  153. package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
  154. package/dist/agent-src/rules/session-canary.md +0 -1
  155. package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
  156. package/dist/agent-src/rules/size-enforcement.md +0 -1
  157. package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
  158. package/dist/agent-src/rules/skill-quality.md +0 -1
  159. package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
  160. package/dist/agent-src/rules/source-confidentiality.md +0 -1
  161. package/dist/agent-src/rules/source-discovery-gate.md +0 -1
  162. package/dist/agent-src/rules/source-of-truth.md +0 -1
  163. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
  164. package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
  165. package/dist/agent-src/rules/symfony-routing.md +1 -2
  166. package/dist/agent-src/rules/think-before-action.md +0 -1
  167. package/dist/agent-src/rules/token-budget-discipline.md +14 -48
  168. package/dist/agent-src/rules/token-efficiency.md +0 -1
  169. package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
  170. package/dist/agent-src/rules/tool-safety.md +0 -1
  171. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  172. package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
  173. package/dist/agent-src/rules/upstream-proposal.md +0 -1
  174. package/dist/agent-src/rules/user-interaction.md +0 -1
  175. package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
  176. package/dist/agent-src/scripts/gate_budget.ts +47 -23
  177. package/dist/agent-src/scripts/gate_execute.ts +12 -4
  178. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
  179. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
  180. package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
  181. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
  182. package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
  183. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
  184. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  185. package/dist/agent-src/skills/canvas-design/SKILL.md +4 -2
  186. package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
  187. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
  188. package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
  189. package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
  190. package/dist/agent-src/skills/database/data/manifest.json +2 -2
  191. package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
  192. package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +13 -10
  193. package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
  194. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  195. package/dist/agent-src/skills/fe-design/references/design-patterns.md +49 -2
  196. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  197. package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
  198. package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
  199. package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
  200. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
  201. package/dist/agent-src/skills/iconography/SKILL.md +4 -2
  202. package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
  203. package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
  204. package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
  205. package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
  206. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  207. package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
  208. package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
  209. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
  210. package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
  211. package/dist/agent-src/skills/svg-authoring/SKILL.md +318 -0
  212. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
  213. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  214. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  215. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  216. package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
  217. package/dist/agent-src/templates/AGENTS.md +1 -1
  218. package/dist/agent-src/templates/agent-settings.md +46 -129
  219. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
  220. package/dist/agent-src/templates/command.md +2 -2
  221. package/dist/agent-src/templates/roadmaps.md +6 -1
  222. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  223. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  224. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  225. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  226. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  227. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  228. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  229. package/dist/agent-src/templates/skill.md +1 -1
  230. package/dist/cli/commands/uiRender.js +201 -4
  231. package/dist/cli/commands/uiRenderAsset.js +1308 -0
  232. package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
  233. package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
  234. package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
  235. package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
  236. package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
  237. package/dist/cli/main.js +47 -1
  238. package/dist/cli/registry.js +2 -1
  239. package/dist/cli-delegate/check_update_banner.js +195 -119
  240. package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-4DBG5K7M.js} +5 -5
  241. package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
  242. package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
  243. package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
  244. package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
  245. package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
  246. package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
  247. package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
  248. package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
  249. package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
  250. package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
  251. package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
  252. package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
  253. package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
  254. package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
  255. package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
  256. package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
  257. package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
  258. package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
  259. package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-TMWYUOK4.js} +75 -12
  260. package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
  261. package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
  262. package/dist/cli-delegate/cmd_analyze_session.js +223 -43
  263. package/dist/cli-delegate/cmd_brand_status.js +3 -2
  264. package/dist/cli-delegate/cmd_conformance.js +489 -238
  265. package/dist/cli-delegate/cmd_converge.js +3 -3
  266. package/dist/cli-delegate/cmd_doctor.js +15 -12
  267. package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
  268. package/dist/cli-delegate/cmd_explain.js +43 -19
  269. package/dist/cli-delegate/cmd_export.js +10 -10
  270. package/dist/cli-delegate/cmd_git_convention.js +1851 -0
  271. package/dist/cli-delegate/cmd_handoff.js +40 -21
  272. package/dist/cli-delegate/cmd_mcp_available.js +3 -2
  273. package/dist/cli-delegate/cmd_migrate.js +3 -3
  274. package/dist/cli-delegate/cmd_packs_active.js +4 -3
  275. package/dist/cli-delegate/cmd_prune.js +10 -10
  276. package/dist/cli-delegate/cmd_route_audit.js +7 -7
  277. package/dist/cli-delegate/cmd_route_explain.js +5 -5
  278. package/dist/cli-delegate/cmd_session_recycle.js +9 -7
  279. package/dist/cli-delegate/cmd_settings_check.js +54 -7
  280. package/dist/cli-delegate/cmd_settings_get.js +18 -8
  281. package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
  282. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  283. package/dist/cli-delegate/cmd_sync.js +10 -10
  284. package/dist/cli-delegate/cmd_uninstall.js +10 -10
  285. package/dist/cli-delegate/cmd_update.js +7 -7
  286. package/dist/cli-delegate/cmd_upgrade.js +7 -7
  287. package/dist/cli-delegate/cmd_validate.js +10 -10
  288. package/dist/cli-delegate/cmd_versions.js +5 -5
  289. package/dist/cli-delegate/gate_budget.js +1 -1
  290. package/dist/cli-delegate/gate_execute.js +2 -2
  291. package/dist/cli-delegate/roadmap_gates.js +2 -2
  292. package/dist/discovery/deprecation-report.md +1 -1
  293. package/dist/discovery/discovery-manifest.json +171 -107
  294. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  295. package/dist/discovery/discovery-manifest.summary.md +7 -7
  296. package/dist/discovery/dormancy-report.md +1 -1
  297. package/dist/discovery/orphan-report.md +1 -1
  298. package/dist/discovery/packs.json +41 -22
  299. package/dist/discovery/trust-report.md +3 -3
  300. package/dist/discovery/workspaces.json +16 -11
  301. package/dist/hooks/dispatch.js +2520 -1924
  302. package/dist/hooks/dispatch.sha256 +1 -1
  303. package/dist/hooks/svg_rules.chunk.cjs +1626 -0
  304. package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
  305. package/dist/install/install.mjs +462 -431
  306. package/dist/install/installThinLayer.js +40 -12
  307. package/dist/install/installedRuleLinks.js +105 -19
  308. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  309. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
  310. package/dist/mcp/registry-manifest.json +5 -5
  311. package/dist/mcp/server.json +2 -2
  312. package/dist/mcp/server.mjs +3063 -2160
  313. package/dist/router.json +1 -1
  314. package/dist/scripts/_lib/agent_settings.js +15 -120
  315. package/dist/scripts/_lib/compile_time_toggles.js +12 -21
  316. package/dist/scripts/_lib/git_convention.js +232 -0
  317. package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
  318. package/dist/scripts/_lib/installed_layer.js +344 -18
  319. package/dist/scripts/_lib/package_root.js +68 -0
  320. package/dist/scripts/_lib/rule_law_section.js +1 -1
  321. package/dist/scripts/_lib/scan_scope.js +105 -0
  322. package/dist/scripts/_lib/settings_removed_keys.js +168 -0
  323. package/dist/scripts/_lib/svg_dom.js +284 -0
  324. package/dist/scripts/_lib/svg_geometry.js +477 -0
  325. package/dist/scripts/_lib/svg_motion.js +179 -0
  326. package/dist/scripts/_lib/svg_rules.js +1337 -0
  327. package/dist/scripts/_lib/svg_urls.js +67 -0
  328. package/dist/scripts/_lib/thin_rules.js +80 -3
  329. package/dist/scripts/lint_svg_asset.js +324 -0
  330. package/dist/server/app.js +2 -1
  331. package/dist/server/gitKeysGate.js +105 -0
  332. package/dist/server/routes/settings.js +67 -8
  333. package/dist/server/routes/wizard.js +4 -0
  334. package/dist/server/schemas/settings.js +23 -81
  335. package/dist/shared/skillRanking.js +30 -4
  336. package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
  337. package/dist/ui/index.html +1 -1
  338. package/docs/MIGRATION.md +72 -1
  339. package/docs/contracts/settings-classes.md +35 -65
  340. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  341. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  342. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  343. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  344. package/docs/guidelines/agent-infra/layered-settings.md +13 -1
  345. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  346. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  347. package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
  348. package/docs/guidelines/design-antipatterns.md +1 -1
  349. package/docs/guidelines/php/git.md +15 -2
  350. package/package.json +4 -3
  351. package/src/agent-src/scripts/gate_budget.ts +47 -23
  352. package/src/agent-src/scripts/gate_execute.ts +12 -4
  353. package/src/agent-src/templates/AGENTS.md +1 -1
  354. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  355. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  356. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  357. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  358. package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  359. package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  360. package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  361. package/src/config/agent-settings.template.yml +79 -312
  362. package/src/config/agents-paths.yml +16 -0
  363. package/src/config/assurance-capability-registry.json +7 -3
  364. package/src/config/ci-local-parity.yml +3 -0
  365. package/src/config/continuity-surface.json +3 -3
  366. package/src/config/discovery/packs.yml +17 -1
  367. package/src/config/evaluator-budgets.json +19 -6
  368. package/src/config/gate-coverage.yml +65 -23
  369. package/src/config/gate-violation-baselines.json +56 -16
  370. package/src/config/gitignore-block.txt +19 -0
  371. package/src/config/hook-bundle-budget.json +1 -1
  372. package/src/config/release-gate-locality.yml +2 -1
  373. package/src/config/routing-coverage-seed.json +55 -6
  374. package/src/config/rule-law-ceilings.json +12 -6
  375. package/src/config/rule-obligations.json +833 -0
  376. package/src/install/installThinLayer.ts +76 -10
  377. package/src/install/installedRuleLinks.ts +105 -17
  378. package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
  379. package/src/scripts/_cli/cmd_conformance.ts +13 -2
  380. package/src/scripts/_cli/cmd_doctor.ts +10 -10
  381. package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
  382. package/src/scripts/_cli/cmd_explain.ts +72 -14
  383. package/src/scripts/_cli/cmd_git_convention.ts +637 -0
  384. package/src/scripts/_cli/cmd_settings_check.ts +66 -8
  385. package/src/scripts/_cli/cmd_settings_get.ts +18 -3
  386. package/src/scripts/_cli/doctor_execution.ts +72 -1
  387. package/src/scripts/_dispatch.bash +37 -2
  388. package/src/scripts/_lib/agent_settings.ts +15 -124
  389. package/src/scripts/_lib/blocked_by_marker.ts +1 -1
  390. package/src/scripts/_lib/compile_time_toggles.ts +12 -21
  391. package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
  392. package/src/scripts/_lib/git_base_ref.ts +92 -0
  393. package/src/scripts/_lib/git_convention.ts +291 -0
  394. package/src/scripts/_lib/git_convention_carrier.ts +389 -0
  395. package/src/scripts/_lib/git_convention_grammar.ts +246 -0
  396. package/src/scripts/_lib/git_convention_measure.ts +344 -0
  397. package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
  398. package/src/scripts/_lib/graph_feeder_record.ts +236 -13
  399. package/src/scripts/_lib/installed_layer.ts +448 -23
  400. package/src/scripts/_lib/knowledge_global.ts +14 -1
  401. package/src/scripts/_lib/module_reach.ts +456 -0
  402. package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
  403. package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
  404. package/src/scripts/_lib/ratification_artifact.ts +220 -1
  405. package/src/scripts/_lib/ratification_subject.ts +92 -0
  406. package/src/scripts/_lib/release_findings_ingest.ts +15 -7
  407. package/src/scripts/_lib/release_highlights.ts +5 -0
  408. package/src/scripts/_lib/rule_law_section.ts +1 -1
  409. package/src/scripts/_lib/rule_obligations.ts +205 -0
  410. package/src/scripts/_lib/self_repair.ts +1 -1
  411. package/src/scripts/_lib/settings_removed_keys.ts +173 -0
  412. package/src/scripts/_lib/svg_dom.ts +318 -0
  413. package/src/scripts/_lib/svg_geometry.ts +480 -0
  414. package/src/scripts/_lib/svg_motion.ts +208 -0
  415. package/src/scripts/_lib/svg_rules.ts +1453 -0
  416. package/src/scripts/_lib/svg_urls.ts +72 -0
  417. package/src/scripts/_lib/test_red_state.ts +5 -0
  418. package/src/scripts/_lib/thin_rules.ts +83 -3
  419. package/src/scripts/_lib/touched_file_quality.ts +142 -6
  420. package/src/scripts/_lib/verification_command.ts +59 -0
  421. package/src/scripts/_lib/verify_clause.ts +27 -17
  422. package/src/scripts/_lib/worker_budget.ts +1 -1
  423. package/src/scripts/adr/regenerate_index.ts +16 -1
  424. package/src/scripts/ai_council/config.ts +7 -7
  425. package/src/scripts/ai_council/modification_review.ts +100 -0
  426. package/src/scripts/ai_council/modification_review_questions.ts +90 -0
  427. package/src/scripts/ai_council/orchestrator.ts +5 -5
  428. package/src/scripts/ai_council/spend_gate.ts +18 -7
  429. package/src/scripts/ai_team/config.ts +11 -16
  430. package/src/scripts/audit_user_type_axis.ts +20 -8
  431. package/src/scripts/bench_ab_clone.ts +1 -2
  432. package/src/scripts/bench_concern_spawn_path.ts +129 -0
  433. package/src/scripts/bench_graph_feeder_latency.ts +584 -0
  434. package/src/scripts/check_agent_artifact_location.ts +36 -0
  435. package/src/scripts/check_branch_freshness.ts +147 -24
  436. package/src/scripts/check_enforcement_coverage.ts +130 -0
  437. package/src/scripts/check_evaluator_budgets.ts +4 -0
  438. package/src/scripts/check_finding_dispositions.ts +88 -25
  439. package/src/scripts/check_gate_coverage.ts +4 -3
  440. package/src/scripts/check_gate_reachability.ts +48 -1
  441. package/src/scripts/check_generator_sync.ts +48 -0
  442. package/src/scripts/check_hook_bundle_composition.ts +107 -0
  443. package/src/scripts/check_kernel_edit_ratified.ts +86 -6
  444. package/src/scripts/check_pack_size.ts +1 -1
  445. package/src/scripts/check_release_manifest_content.ts +189 -0
  446. package/src/scripts/check_standing_rule_delivery.ts +96 -0
  447. package/src/scripts/check_suppression_hygiene.ts +2 -5
  448. package/src/scripts/ci_settle.ts +42 -5
  449. package/src/scripts/classify_merge_risk.ts +320 -0
  450. package/src/scripts/closure_scan.ts +91 -1
  451. package/src/scripts/command_suggester/settings.ts +8 -108
  452. package/src/scripts/command_suggester/types.ts +4 -5
  453. package/src/scripts/consumer_matrix.ts +102 -0
  454. package/src/scripts/context_hygiene_hook.ts +13 -23
  455. package/src/scripts/cost/preflight.mjs +12 -1
  456. package/src/scripts/council_cli.ts +7 -7
  457. package/src/scripts/dispatch_r2_reviewer.ts +24 -11
  458. package/src/scripts/explain_run.ts +8 -13
  459. package/src/scripts/generate_git_convention_grammar.ts +127 -0
  460. package/src/scripts/generate_host_cost_table.ts +20 -3
  461. package/src/scripts/handoff_context_hook.ts +86 -37
  462. package/src/scripts/hook_manifest.json +1 -1
  463. package/src/scripts/hook_manifest.yaml +25 -6
  464. package/src/scripts/hooks/block_config_weakening.ts +48 -5
  465. package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
  466. package/src/scripts/hooks/block_speaking_inbox_dir.ts +16 -1
  467. package/src/scripts/hooks/concern_registry.ts +2 -0
  468. package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
  469. package/src/scripts/hooks/design_pass_hook.ts +157 -3
  470. package/src/scripts/hooks/evidence_independence.ts +12 -4
  471. package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
  472. package/src/scripts/hooks/push_settle_hook.ts +4 -3
  473. package/src/scripts/hooks/rule_inject_hook.ts +44 -3
  474. package/src/scripts/hooks/state_io.ts +8 -4
  475. package/src/scripts/hooks/svg_obligation.ts +497 -0
  476. package/src/scripts/hooks/svg_rules_loader.ts +133 -0
  477. package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
  478. package/src/scripts/hooks/turn_end_gate_hook.ts +6 -3
  479. package/src/scripts/install-hooks.sh +42 -14
  480. package/src/scripts/install.ts +7 -31
  481. package/src/scripts/lint_blocker_citations.ts +198 -0
  482. package/src/scripts/lint_consolidation_lineage.ts +6 -3
  483. package/src/scripts/lint_design_quality.ts +60 -12
  484. package/src/scripts/lint_evidence_artifacts.ts +9 -0
  485. package/src/scripts/lint_hook_concern_budget.ts +10 -21
  486. package/src/scripts/lint_motion_authority_drift.ts +27 -0
  487. package/src/scripts/lint_pack_boundaries.ts +406 -28
  488. package/src/scripts/lint_roadmap_blockers.ts +282 -29
  489. package/src/scripts/lint_roadmap_complexity.ts +4 -2
  490. package/src/scripts/lint_rule_law_section.ts +151 -21
  491. package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
  492. package/src/scripts/lint_settings_classes.ts +1 -1
  493. package/src/scripts/lint_svg_asset.ts +365 -0
  494. package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
  495. package/src/scripts/lint_workflow_security.ts +12 -1
  496. package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
  497. package/src/scripts/model_rule_injection.ts +3 -3
  498. package/src/scripts/onboarding_gate_hook.ts +7 -6
  499. package/src/scripts/print_required_checks.ts +15 -3
  500. package/src/scripts/probe_host_compliance.ts +33 -5
  501. package/src/scripts/probe_turnaround.ts +183 -3
  502. package/src/scripts/ratification_header.ts +77 -0
  503. package/src/scripts/refusal_envelope.ts +138 -0
  504. package/src/scripts/release_publication.ts +29 -3
  505. package/src/scripts/report_dispatch_import_closure.ts +76 -0
  506. package/src/scripts/report_installed_rule_links.ts +118 -1
  507. package/src/scripts/report_module_reach.ts +212 -0
  508. package/src/scripts/report_obligation_mechanism.ts +16 -18
  509. package/src/scripts/report_parked_blockers.ts +222 -0
  510. package/src/scripts/report_required_checks_drift.ts +196 -0
  511. package/src/scripts/report_skill_ranker_confusion.ts +103 -2
  512. package/src/scripts/report_standing_payload_by_host.ts +1 -1
  513. package/src/scripts/routing_doctor.ts +2 -2
  514. package/src/scripts/schemas/agent-settings.schema.json +17 -31
  515. package/src/scripts/schemas/command.schema.json +1 -1
  516. package/src/scripts/schemas/skill.schema.json +1 -1
  517. package/src/scripts/self_review_gate.ts +39 -2
  518. package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
  519. package/src/scripts/sync_pr_branch.ts +403 -132
  520. package/src/scripts/trigger_eval_grandfather.json +0 -16
  521. package/src/server/schemas/settings.ts +33 -177
  522. package/src/shared/skillRanking.ts +53 -4
  523. package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
  524. package/src/scripts/_lib/config_chain.ts +0 -477
  525. package/src/scripts/_lib/conformance_report.ts +0 -403
  526. package/src/scripts/_lib/eval_discrimination.ts +0 -95
  527. package/src/scripts/_lib/evaluator_promotion.ts +0 -225
  528. package/src/scripts/_lib/file_slicer.ts +0 -117
  529. package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
  530. package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
  531. package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
  532. package/src/scripts/_lib/role_split.ts +0 -338
@@ -0,0 +1,72 @@
1
+ /**
2
+ * How a browser reads the URLs and names in an SVG, for the safety rules in
3
+ * `svg_rules.ts`: references decoded, controls stripped, CSS escapes resolved,
4
+ * and an element prefix stripped only where it is bound to the SVG namespace.
5
+ * Its own module so `svg_rules.ts` stays under the source-size ceiling.
6
+ */
7
+
8
+ /** Prefixes the document binds to the SVG namespace (`xmlns:svg="…/2000/svg"`). */
9
+ export function svgPrefixes(content: string): Set<string> {
10
+ const out = new Set<string>();
11
+ const re = /xmlns:([\w.-]+)\s*=\s*["']http:\/\/www\.w3\.org\/2000\/svg["']/gi;
12
+ let m: RegExpExecArray | null;
13
+ while ((m = re.exec(content)) !== null) out.add((m[1] ?? '').toLowerCase());
14
+ return out;
15
+ }
16
+
17
+ /** The SVG local name: `svg:script` is a `script` where `svg` is bound to SVG; `foo:script` is not. */
18
+ export function localName(name: string, prefixes: ReadonlySet<string>): string {
19
+ const colon = name.indexOf(':');
20
+ return colon !== -1 && prefixes.has(name.slice(0, colon)) ? name.slice(colon + 1) : name;
21
+ }
22
+
23
+ /** Attributes read from the raw tag, unquoted values included — HTML parses those. */
24
+ export function rawAttrs(raw: string): Record<string, string> {
25
+ const out: Record<string, string> = {};
26
+ const re = /([\w:.-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"'`=]+))/g;
27
+ let m: RegExpExecArray | null;
28
+ while ((m = re.exec(raw)) !== null) out[(m[1] ?? '').toLowerCase()] = m[2] ?? m[3] ?? m[4] ?? '';
29
+ return out;
30
+ }
31
+
32
+ /** Attributes whose value is followed as a URL. */
33
+ export const URL_ATTRS = new Set(['href', 'xlink:href', 'src']);
34
+
35
+
36
+ /** A URL that executes or opens a document when followed. */
37
+ export const isActiveUrl = (raw: string): boolean => /^(javascript:|data:text\/html)/i.test(resolvedUrl(raw));
38
+
39
+ const NAMED_URL_ENTITIES: Record<string, string> = {
40
+ colon: ':', sol: '/', tab: '\t', newline: '\n', period: '.', lpar: '(', rpar: ')', amp: '&',
41
+ };
42
+
43
+ /**
44
+ * The URL a browser would actually resolve from an attribute value: character
45
+ * references decoded, leading/trailing C0 controls and spaces stripped, tab and
46
+ * newline removed anywhere. The trailing `;` of a reference is optional on
47
+ * purpose: an `.svg` parsed as XML needs it, but the same graphic inlined in an
48
+ * HTML host is parsed by the HTML tokenizer, which decodes `&#106avascript:`
49
+ * too — over-reading XML here costs precision, under-reading HTML costs a miss.
50
+ * The raw value is attacker-chosen, so a scheme test
51
+ * against it is a test of one spelling — ` https:`, `ht\ttps:`, `&#106;avascript:`
52
+ * all load, and all passed.
53
+ */
54
+ export function resolvedUrl(raw: string): string {
55
+ const decoded = raw.replace(/&(?:#x([0-9a-f]+)|#(\d+)|([a-z]+));?/gi, (m, hex, dec, name) => {
56
+ const cp = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : NaN;
57
+ if (!Number.isNaN(cp)) return cp <= 0x10ffff ? String.fromCodePoint(cp) : m;
58
+ return NAMED_URL_ENTITIES[(name as string).toLowerCase()] ?? m;
59
+ });
60
+ return decoded.replace(/^[\u0000- ]+|[\u0000- ]+$/g, '').replace(/[\t\n\r]/g, '');
61
+ }
62
+
63
+ /** CSS escapes decoded: `\\68 ` and `\\h` both read `h`. */
64
+ export function cssUnescape(raw: string): string {
65
+ return raw.replace(/\\([0-9a-f]{1,6})\s?|\\(.)/gi, (m, hex, ch) => {
66
+ if (hex) {
67
+ const cp = parseInt(hex, 16);
68
+ return cp <= 0x10ffff ? String.fromCodePoint(cp) : m;
69
+ }
70
+ return ch as string;
71
+ });
72
+ }
@@ -10,6 +10,11 @@
10
10
  * This module is that emission, so the registry entry moves in the same change
11
11
  * rather than being left describing a gap that closed.
12
12
  *
13
+ * DATED 2026-10-06. The emission exists and is tested, but nothing calls it:
14
+ * this writer has no production caller, so the registry row was corrected back
15
+ * to `degraded` the same day. The caller belongs to the stub that owns it —
16
+ * whoever lands it sets the row back to `available`.
17
+ *
13
18
  * WHAT IT IS NOT. It is not a test runner, and it does not decide whether a
14
19
  * failure is a legitimate RED. The failure CLASSES belong to the TDD skill
15
20
  * (`src/skills/test-driven-development/SKILL.md`, Test-Red row) and this module
@@ -284,15 +284,95 @@ function _title(s: string): string {
284
284
  * Exported so the WRITER and every DETECTOR share one definition. A gate that
285
285
  * re-spelled this string would drift from the writer silently, and the failure
286
286
  * would be invisible in exactly the direction that matters: a stub the gate
287
- * fails to recognise reads as a complete rule body.
287
+ * fails to recognise reads as a complete rule body. Two gates had done exactly
288
+ * that until step 2.1 of `road-to-a-thinned-layer-measured-in-one-unit`; both
289
+ * import this now.
290
+ *
291
+ * SHORTENED 2026-10-06 from 47 characters to 27 (step 2.2). It is paid once per
292
+ * stub and there were 89 stubs on the measured layer, so the sentence cost
293
+ * 4,183 characters of a 97,496-character standing total; at 27 it costs 2,403,
294
+ * a saving of 1,780 = 20 x 89.
295
+ *
296
+ * WHAT THE SHORTENING WAS NOT ALLOWED TO DO: drop the instruction. This is the
297
+ * only standing text in the whole layer that says what a stub is FOR — "load
298
+ * the body" occurs in no kernel rule and in neither root instruction file — so
299
+ * a bare token like `> thin` would have saved more and left nothing that could
300
+ * be followed. The decision record (D2, K6) rejected that explicitly: nothing
301
+ * in this repository can check whether an instruction nobody states is still
302
+ * obeyed.
303
+ *
304
+ * WHY IT MUST STAY LONG ENOUGH TO BE UNIQUE: {@link is_thin_entry} is a
305
+ * substring test over the whole file, so a marker short or generic enough to
306
+ * occur inside ordinary rule prose would make that rule read as a stub — and
307
+ * nine rule files carry blockquote lines. `thin_marker_unique_in_corpus.test.ts`
308
+ * runs the constant against every rule body in `src/rules/` and against every
309
+ * entry `build_thin` emits, in both directions, which is the check that bounds
310
+ * any further shortening.
288
311
  */
289
- export const THIN_ENTRY_MARKER = '> Routed rule — load the body on trigger-match.';
312
+ export const THIN_ENTRY_MARKER = '> Load the body on a match.';
290
313
 
291
314
  /** Is this projected entry a pointer stub rather than a rule body? */
292
315
  export function is_thin_entry(text: string): boolean {
293
316
  return text.includes(THIN_ENTRY_MARKER);
294
317
  }
295
318
 
319
+ /**
320
+ * What introduces a stub's body pointer. One writer, one reader.
321
+ *
322
+ * A BARE PATH SINCE 2026-10-06 (step 2.3 of
323
+ * `road-to-a-thinned-layer-measured-in-one-unit`). The pointer used to be a
324
+ * markdown link, ``Body: [`<id>`](<prefix><id>.md)``, whose link TEXT repeated
325
+ * the rule id the target already ends in. That cost `6 + len(id)` per stub over
326
+ * the bare form — 2,359 characters across the 89 stubs of the measured layer,
327
+ * 534 of it pure syntax and the rest the id written a second time.
328
+ *
329
+ * Nothing followed the link as a link. Under `delivery` the hook loads the body
330
+ * and never reads the pointer at all; under `thin` an agent reads the path. A
331
+ * markdown link renders in neither case, so the syntax bought rendering nobody
332
+ * was doing.
333
+ */
334
+ export const THIN_BODY_POINTER_PREFIX = 'Body: ';
335
+
336
+ /**
337
+ * The pointer, as the WRITER emits it — exported so a detector cannot re-spell
338
+ * it, which is the same drift {@link THIN_ENTRY_MARKER} documents one screen up
339
+ * and which two gates had already committed there.
340
+ *
341
+ * WHAT IT CAPTURES is the whole tail of the line from `Body: ` to its end, and
342
+ * that is the intended semantic rather than an accident of greediness: the
343
+ * writer emits the pointer LAST on its line, so the tail IS the path. A review
344
+ * round proposed a lazy `(.+?\.md)` to stop at the first `.md`; measured, it
345
+ * changes nothing, because `\s*$` forces the match to reach end of line either
346
+ * way and a lazy quantifier simply backtracks forward to the same place. The
347
+ * greedy form is kept and the property is pinned by a test, so the next reader
348
+ * meets the measurement instead of repeating the proposal.
349
+ *
350
+ * ANCHORED TO END OF LINE, NOT `\S+`. The pointer is the last thing on its
351
+ * line, and a package root may contain spaces; `\S+` would silently stop at the
352
+ * first one and report a well-formed pointer as missing.
353
+ *
354
+ * COMPOSED FROM {@link THIN_BODY_POINTER_PREFIX} rather than re-spelling it.
355
+ * The constant exists so a reader cannot hold its own copy, and a pattern six
356
+ * lines below it holding a literal `Body: ` would have broken that invariant in
357
+ * the file that states it.
358
+ */
359
+ export const THIN_BODY_POINTER_RE = (() => {
360
+ const lit = THIN_BODY_POINTER_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
361
+ // THE LAST PREFIX ON THE LINE, NOT THE FIRST. `thin_entry` puts the rule's
362
+ // own `description` on the SAME line ahead of the pointer, so a description
363
+ // containing the literal `Body: ` used to start the match inside the
364
+ // description and capture it as part of the path — `has_body_pointer` stayed
365
+ // true while the extraction was wrong, which is a wrong assertion rather
366
+ // than a visible failure. Forbidding a second prefix inside the capture
367
+ // makes the first viable start the last occurrence, which is the pointer.
368
+ return new RegExp(`${lit}((?:(?!${lit}).)+\\.md)\\s*$`, 'm');
369
+ })();
370
+
371
+ /** Does this entry carry a body pointer the writer would recognise? */
372
+ export function has_body_pointer(text: string): boolean {
373
+ return THIN_BODY_POINTER_RE.test(text);
374
+ }
375
+
296
376
  /**
297
377
  * Where a stub tells a reader the body actually is.
298
378
  *
@@ -356,7 +436,7 @@ export function thin_entry(
356
436
  return (
357
437
  `## ${title}\n` +
358
438
  `${THIN_ENTRY_MARKER}${fires} ${desc} ` +
359
- `Body: [\`${rule_id}\`](${bodyLinkPrefix}${rule_id}.md)\n`
439
+ `${THIN_BODY_POINTER_PREFIX}${bodyLinkPrefix}${rule_id}.md\n`
360
440
  );
361
441
  }
362
442
 
@@ -89,6 +89,22 @@ export interface QualityRun {
89
89
  readonly output_head: readonly string[];
90
90
  readonly skipped: SkipReason | null;
91
91
  readonly files: readonly string[];
92
+ /**
93
+ * Matched files the tool reported it declined to look at. A run where EVERY
94
+ * matched file is listed here and the tool exited 0 is a verdict about
95
+ * nothing, so `exit_code` is `null` for it — the readings page § 5(a) found
96
+ * that row recorded `0, skipped: null`, the exact shape of a pass. A field
97
+ * rather than a fifth `SkipReason` (D2): a partly-ignored run keeps its real
98
+ * exit code, and a skip reason cannot sit beside a verdict.
99
+ */
100
+ readonly ignored_files: readonly string[];
101
+ /**
102
+ * Type-check commands the resolver emitted that produced no verdict on this
103
+ * turn — unscoped, absent or mutating. Identical on every record of the turn,
104
+ * so ANY single row says that a `0` beside it was a lint verdict and not a
105
+ * type verdict (§ 5(b): `tsc --noEmit` is unscoped on every stop).
106
+ */
107
+ readonly typecheck_not_run: readonly string[];
92
108
  readonly at: string;
93
109
  }
94
110
 
@@ -112,8 +128,21 @@ interface ToolSpec {
112
128
  * the resolver's by exactly the flag that makes it read-only.
113
129
  */
114
130
  readonly check_form: boolean;
131
+ /**
132
+ * A line the tool prints, exit 0, for an input its own config ignores. Per
133
+ * row because the wording is the tool's (D1); a row without one reads no
134
+ * output as an ignore, which keeps the pre-existing behaviour rather than
135
+ * guessing at a message the tool might print.
136
+ */
137
+ readonly ignored_signal?: RegExp;
115
138
  }
116
139
 
140
+ /**
141
+ * ESLint 9's stylish report for an ignored input: the absolute path on its own
142
+ * line, then this indented warning. Pinned verbatim by the ignored-file fixture.
143
+ */
144
+ const ESLINT_IGNORED = /^\s+\d+:\d+\s+warning\s+File ignored because of a matching ignore pattern\b/;
145
+
117
146
  const JS_EXTENSIONS = ['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx', '.mts', '.cts'] as const;
118
147
 
119
148
  /**
@@ -124,7 +153,15 @@ const JS_EXTENSIONS = ['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx', '.mts', '.c
124
153
  * and absence is what produces `skipped: unscoped`.
125
154
  */
126
155
  const SCOPED_FORMS: ReadonlyMap<string, ToolSpec> = new Map<string, ToolSpec>([
127
- ['npx eslint .', { argv: ['npx', 'eslint'], extensions: JS_EXTENSIONS, check_form: false }],
156
+ [
157
+ 'npx eslint .',
158
+ {
159
+ argv: ['npx', 'eslint'],
160
+ extensions: JS_EXTENSIONS,
161
+ check_form: false,
162
+ ignored_signal: ESLINT_IGNORED,
163
+ },
164
+ ],
128
165
  [
129
166
  'vendor/bin/phpstan analyse',
130
167
  { argv: ['vendor/bin/phpstan', 'analyse'], extensions: ['.php'], check_form: false },
@@ -153,6 +190,38 @@ const SCOPED_FORMS: ReadonlyMap<string, ToolSpec> = new Map<string, ToolSpec>([
153
190
  */
154
191
  const MUTATING_WITHOUT_CHECK_FORM: ReadonlySet<string> = new Set<string>([]);
155
192
 
193
+ /**
194
+ * Resolver commands with no file-scoped form, unscoped ON PURPOSE (rule 3).
195
+ *
196
+ * Named so the parity test can tell a deliberate absence from `SCOPED_FORMS`
197
+ * apart from a resolver command nobody classified: every command the resolver
198
+ * emits is a scoped key, a mutating key, or on this list — or a test is red.
199
+ */
200
+ export const UNSCOPED_ON_PURPOSE: readonly string[] = [
201
+ 'npx tsc --noEmit',
202
+ 'go vet ./...',
203
+ 'cargo clippy',
204
+ ];
205
+
206
+ /** The keys of `SCOPED_FORMS`, for the parity test. */
207
+ export const SCOPED_FORM_COMMANDS: readonly string[] = [...SCOPED_FORMS.keys()];
208
+
209
+ /** The keys of `MUTATING_WITHOUT_CHECK_FORM`, for the parity test. */
210
+ export const MUTATING_COMMANDS: readonly string[] = [...MUTATING_WITHOUT_CHECK_FORM];
211
+
212
+ /**
213
+ * Resolver commands whose verdict is a type verdict. `go vet` and `cargo clippy`
214
+ * both compile the package, so a type error stops them; ESLint, ruff and pint do
215
+ * not type-check, which is the whole of § 5(b).
216
+ */
217
+ export const TYPE_CHECK_COMMANDS: ReadonlySet<string> = new Set<string>([
218
+ 'npx tsc --noEmit',
219
+ 'vendor/bin/phpstan analyse',
220
+ 'mypy .',
221
+ 'go vet ./...',
222
+ 'cargo clippy',
223
+ ]);
224
+
156
225
  function extensionOf(file: string): string {
157
226
  const base = path.basename(file);
158
227
  const dot = base.lastIndexOf('.');
@@ -253,7 +322,7 @@ function defaultSpawn(
253
322
  export function runTouchedFileQuality(opts: RunOptions): QualityRun[] {
254
323
  const timeout_ms = opts.timeout_ms ?? DEFAULT_TIMEOUT_MS;
255
324
  const spawn = opts.spawn ?? defaultSpawn;
256
- const out: QualityRun[] = [];
325
+ const out: Omit<QualityRun, 'typecheck_not_run'>[] = [];
257
326
  for (const plan of planQualityRuns(opts.commands, opts.files)) {
258
327
  if (plan.argv === null) {
259
328
  out.push({
@@ -263,6 +332,7 @@ export function runTouchedFileQuality(opts: RunOptions): QualityRun[] {
263
332
  output_head: [],
264
333
  skipped: plan.skipped,
265
334
  files: [],
335
+ ignored_files: [],
266
336
  at: now(),
267
337
  });
268
338
  continue;
@@ -282,17 +352,69 @@ export function runTouchedFileQuality(opts: RunOptions): QualityRun[] {
282
352
  // tool is a wrapper script whose own dependency is missing. Same meaning
283
353
  // as ENOENT for this module's purposes, and the same bucket in 2.1.
284
354
  const absent = enoent || status === 127;
355
+ const signal = SCOPED_FORMS.get(plan.source_command)?.ignored_signal;
356
+ const ignored =
357
+ absent || signal === undefined ? [] : ignoredFiles(output, signal, plan.files);
358
+ // Every matched file ignored AND exit 0: the tool looked at nothing, so
359
+ // there is no verdict to record. A non-zero exit over the same set stays,
360
+ // because a red the tool raised (a config crash, say) is real.
361
+ const nothingLooked = ignored.length === plan.files.length && status === 0;
285
362
  out.push({
286
363
  command: renderCommand(plan.argv),
287
364
  source_command: plan.source_command,
288
- exit_code: absent ? null : status,
365
+ exit_code: absent || nothingLooked ? null : status,
289
366
  output_head: absent ? [] : headLines(output, OUTPUT_HEAD_LINES),
290
367
  skipped: absent ? 'absent' : null,
291
368
  files: plan.files,
369
+ ignored_files: ignored,
292
370
  at: now(),
293
371
  });
294
372
  }
295
- return out;
373
+ // `no_files` is excluded: no file the type checker reads was touched, so
374
+ // there was nothing on this turn for it to have caught.
375
+ const typecheck_not_run = out
376
+ .filter(
377
+ (r) =>
378
+ TYPE_CHECK_COMMANDS.has(r.source_command) &&
379
+ r.exit_code === null &&
380
+ r.skipped !== 'no_files' &&
381
+ r.skipped !== null,
382
+ )
383
+ .map((r) => r.source_command);
384
+ return out.map((r) => ({ ...r, typecheck_not_run: [...typecheck_not_run] }));
385
+ }
386
+
387
+ /**
388
+ * The matched files the tool's output reports as ignored.
389
+ *
390
+ * The stylish report names the file on an unindented line and the warning on
391
+ * the indented lines under it, so a signal line is attributed to the last path
392
+ * line above it. A signal that cannot be attributed is attributed to the one
393
+ * matched file only when there is exactly one; otherwise it is dropped, so an
394
+ * unreadable report keeps today's behaviour instead of inventing an ignore.
395
+ */
396
+ export function ignoredFiles(
397
+ output: string,
398
+ signal: RegExp,
399
+ files: readonly string[],
400
+ ): string[] {
401
+ const reported: string[] = [];
402
+ let unattributed = false;
403
+ let current: string | null = null;
404
+ for (const line of output.split(/\r\n|\r|\n/)) {
405
+ if (signal.test(line)) {
406
+ if (current === null) unattributed = true;
407
+ else reported.push(normalizePath(current));
408
+ continue;
409
+ }
410
+ if (line !== '' && !/^\s/.test(line)) current = line.trim();
411
+ }
412
+ const hit = files.filter((f) => {
413
+ const want = normalizePath(f);
414
+ return reported.some((r) => r === want || r.endsWith(`/${want}`));
415
+ });
416
+ if (hit.length === 0 && unattributed && files.length === 1) return [...files];
417
+ return hit;
296
418
  }
297
419
 
298
420
  /**
@@ -306,11 +428,25 @@ export function runTouchedFileQuality(opts: RunOptions): QualityRun[] {
306
428
  export const WARN_LINE_MAX_BYTES = 200;
307
429
 
308
430
  export function advisoryLine(runs: readonly QualityRun[]): string | null {
431
+ const ignored = [...new Set(runs.flatMap((r) => r.ignored_files))];
432
+ const ignoredPart =
433
+ ignored.length === 0
434
+ ? ''
435
+ : `ignored ${ignored[0] ?? ''}${ignored.length > 1 ? ` (+${String(ignored.length - 1)} more)` : ''}`;
309
436
  const failed = runs.find((r) => r.skipped === null && r.exit_code !== null && r.exit_code !== 0);
310
- if (failed === undefined) return null;
437
+ if (failed === undefined) {
438
+ // Nothing failed. Silence is right when every file was looked at; when a
439
+ // file was ignored, silence would read as clean, so say what was not seen.
440
+ if (ignored.length === 0) return null;
441
+ return truncateToBytes(
442
+ `touched-file quality: no verdict, ${ignoredPart}`,
443
+ WARN_LINE_MAX_BYTES,
444
+ );
445
+ }
311
446
  const file = failed.files[0] ?? '(no file)';
312
447
  const more = failed.files.length > 1 ? ` (+${String(failed.files.length - 1)} more)` : '';
313
- const line = `touched-file quality: ${failed.source_command} exited ${String(failed.exit_code)} on ${file}${more}`;
448
+ const tail = ignoredPart === '' ? '' : `; ${ignoredPart}`;
449
+ const line = `touched-file quality: ${failed.source_command} exited ${String(failed.exit_code)} on ${file}${more}${tail}`;
314
450
  return truncateToBytes(line, WARN_LINE_MAX_BYTES);
315
451
  }
316
452
 
@@ -271,6 +271,28 @@ function segmentVerifies(rawWords: readonly string[]): boolean {
271
271
  // the old token-anywhere regex accepted it by accident and neither
272
272
  // explicit list named it, so the union seeding missed it too.
273
273
  return rest.some((a) => a === 'test' || a.startsWith('--test'));
274
+ case 'agent-config':
275
+ // NEITHER `ui:render` NOR `xmllint` verifies here, and the first
276
+ // half of that was true, then false, and is true again.
277
+ //
278
+ // Step 3.5 of `road-to-svg-with-a-witness` taught this predicate
279
+ // `ui:render --profile asset`, reasoning that it is the one
280
+ // subcommand which opens the delivered file in a real engine. Step
281
+ // 2.1(b) of `road-to-svg-review-followups` removed it again on
282
+ // review claim C2, which is narrower than the first argument and
283
+ // refutes it: the turn-end gate's TRANSCRIPT path matches a command
284
+ // and never sees an exit code, so a call that rendered nothing —
285
+ // the ordinary case on a machine with no Playwright, where the
286
+ // command also exited 0 until the same day — discharged the
287
+ // obligation from its text alone.
288
+ //
289
+ // What replaces it reads the RENDER instead of the call:
290
+ // `hooks/svg_obligation.ts` matches a manifest to the file's own
291
+ // digest, and accepts a renderer-absent manifest only together with
292
+ // a clean static witness on those same bytes. `xmllint --noout`
293
+ // stays out for its original reason (S6): a file can parse and
294
+ // still be the wrong picture.
295
+ return false;
274
296
  case 'scripts-run': {
275
297
  // `./scripts-run src/scripts/lint_x` verifies; `…/rule_activation_census`
276
298
  // writes a report and asserts nothing, which is why this keys on the
@@ -322,3 +344,40 @@ const _WIDE_CANDIDATE_RE =
322
344
  export function mightBeVerification(command: string): boolean {
323
345
  return _WIDE_CANDIDATE_RE.test(command);
324
346
  }
347
+
348
+ /**
349
+ * `agent-config ui:render … --profile asset`, by shape.
350
+ *
351
+ * Moved here from `hooks/svg_obligation.ts` by finding 3 of this change's
352
+ * SECOND completion review: two detectors need it and one of them is in
353
+ * `_lib`, so a hook module was the wrong home. Re-exported there, so no
354
+ * caller moved.
355
+ */
356
+ export function isAssetRenderCommand(command: string): boolean {
357
+ return /\bui:render\b/.test(command) && /--profile[= ]\s*asset\b/.test(command);
358
+ }
359
+
360
+ /**
361
+ * Did this command ATTEMPT to verify something — as opposed to: did it produce
362
+ * a verdict this gate may read?
363
+ *
364
+ * The distinction is the whole point, and the first review round and the
365
+ * second each saw one half of it. Round one (claim C2) was right that
366
+ * `isVerificationCommand` must NOT learn the asset render: the transcript path
367
+ * never sees an exit code, so the command's TEXT would have discharged the SVG
368
+ * obligation on a machine where the render produced nothing. Round two
369
+ * (finding 3) was right that removing it left detector C — "did any
370
+ * verification command follow the last edit" — unable to see the one command
371
+ * this package PRESCRIBES for an `.svg`, so the prescribed turn was refused.
372
+ *
373
+ * Both hold because they are about different detectors. Detector C asks
374
+ * whether the author tried; it is satisfied by `eslint` and must be satisfied
375
+ * by a render too. The SVG obligation asks what the render FOUND, and still
376
+ * reads the manifest and the file's digest — an attempt that produced nothing
377
+ * discharges nothing there, with a far better reason than detector C's.
378
+ *
379
+ * So: one predicate per question, and `isVerificationCommand` is unchanged.
380
+ */
381
+ export function isVerificationAttempt(command: string): boolean {
382
+ return isVerificationCommand(command) || isAssetRenderCommand(command);
383
+ }
@@ -126,25 +126,35 @@ function lastMatch(re: RegExp, text: string): RegExpExecArray | null {
126
126
  * carries `(?!`)`: a label followed by a backtick is the delimited form, which
127
127
  * branch one already owns.
128
128
  *
129
- * The tail is capped at a single non-space token on purpose. A caller may hand
130
- * this parser a whole step BLOCK already joined into one line, so "the rest of
131
- * the line" can mean "the rest of the step" — and a step that continues after
132
- * its verify clause would then push the expectation away from the end anchor
133
- * and lose it silently. The cost is that a regex expectation here may not
134
- * contain a space; `/[1-9]/` and `/unfalsifiable-verify/` are the shapes in
135
- * use, and a space-bearing expectation loses its arrow loudly (it parses as no
136
- * expectation) rather than half-matching.
129
+ * The tail is bounded by the EXPECTATION'S OWN DELIMITERS, not by the end of
130
+ * the line. A caller may hand this parser a whole step BLOCK already joined
131
+ * into one line, so "the rest of the line" can mean "the rest of the step": an
132
+ * end-anchored tail would lose the expectation of any step that carries prose
133
+ * after its clause. A slash-delimited regex therefore runs to the first
134
+ * UNESCAPED closing `/` — one not preceded by an odd number of backslashes —
135
+ * that is followed by whitespace or the end of the text, and an exit code is
136
+ * one non-space token; both self-terminating, so the step may continue and
137
+ * `-> /[1-9]/ and then note the result` still yields `[1-9]`.
137
138
  *
138
- * THE CAP IS THIS FORM'S, NOT THE GRAMMAR'S — said plainly because an earlier
139
- * revision of this comment implied otherwise. The annotation form is
140
- * `$`-anchored through {@link VERIFY_ARROW_SOURCE} and DOES keep `-> /a b/`;
141
- * this form does not. The two agree on every space-free expectation, which is
142
- * every expectation in the tree. Both directions are pinned by test, so closing
143
- * the gap is a deliberate act against a failing assertion rather than a silent
144
- * drift — which is the failure the WHY ONE PARSER note above exists to prevent,
145
- * and it applies to this module's own two readers first.
139
+ * The word UNESCAPED is load-bearing and was added on 2026-10-11 (step 1.1 of
140
+ * `road-to-svg-review-followups`, review claim C4). The tail used to be a lazy
141
+ * `\/.*?\/(?=\s|$)`, which stops at ANY `/` followed by a space — so a clause
142
+ * ending in ``-> /a\/ b/`` was cut at the escaped slash and parsed to the
143
+ * regex source `a\`. A pattern that deliberately matches a path separator is
144
+ * exactly the case that spells it `\/`, and the truncation was silent: a
145
+ * shorter regex is still a regex, so nothing reported the loss.
146
+ *
147
+ * It was capped at a single non-space token until 2026-10-11, which cost this
148
+ * form every expectation containing a space: `-> /Icon-only button/` parsed as
149
+ * a clause with NO expectation, and nothing reported the loss — the step simply
150
+ * read as unfalsifiable. The two forms now agree on every expectation rather
151
+ * than only the space-free ones; {@link VERIFY_ARROW_SOURCE} stays the single
152
+ * `$`-anchored decision about what an expectation IS, and this regex decides
153
+ * only where the tail ENDS. A bare word stays refused by the constant, so
154
+ * widening the boundary widened no grammar.
146
155
  */
147
- const BACKTICKED_RE = /(?:`verify:`|verify:(?!`))\s*`([^`]+)`[ \t]*((?:->|→)[ \t]*\S+)?/g;
156
+ const BACKTICKED_RE =
157
+ /(?:`verify:`|verify:(?!`))\s*`([^`]+)`[ \t]*((?:->|→)[ \t]*(?:\/(?:[^\\/]|\\.)*\/(?=\s|$)|\S+))?/g;
148
158
 
149
159
  /** Prose after the label. The MANUAL form; the body is bounded separately. */
150
160
  const PROSE_RE = /(?:`verify:`|verify:(?!`))[ \t]*/g;
@@ -9,7 +9,7 @@
9
9
  * error on the wrong rung, not diligence.
10
10
  *
11
11
  * Composes with — replaces nothing:
12
- * - the N=3 validation-loop budget (`autonomous-execution`),
12
+ * - the `execution.fix_loop_max` validation-loop budget (`autonomous-execution`),
13
13
  * - the ADR-109 / `subagent-response-contract` body + 4-status envelope
14
14
  * (`subagent-steering`): the partial result rides as the body of a
15
15
  * `BLOCKED` envelope with `budget_hit: true` as the escalation flag.
@@ -187,11 +187,26 @@ export function scan(d: string): [Row[], Row[], string[]] {
187
187
  * A scope with no refs renders as `—`: a qualifier on nothing is not a
188
188
  * supersession, and printing the prose alone would read as one.
189
189
  */
190
+ /**
191
+ * Escape a `|` for safety inside a Markdown table cell. The free-text scope
192
+ * fields this feeds (`supersedes_scope` / `superseded_scope`) routinely quote
193
+ * a table row from the record they describe — and a quoted row has its own
194
+ * `|` column separators, verbatim, in the frontmatter prose. Unescaped, that
195
+ * splits the generated row into extra columns rather than rendering the quote
196
+ * (found live in ADR-230's and ADR-279's own rows, both quoting the same
197
+ * table cell from ADR-230 § Decision). `refs` itself is never escaped: it is
198
+ * always an `ADR-NNN` token list this generator produces or validates, never
199
+ * free text.
200
+ */
201
+ function escapeCell(text: string): string {
202
+ return text.replaceAll('|', '\\|');
203
+ }
204
+
190
205
  export function supersessionCell(refs: string | undefined, scope: string | undefined): string {
191
206
  const r = (refs ?? '').trim();
192
207
  if (r === '' || r === '—') return '—';
193
208
  const s = (scope ?? '').trim();
194
- return s === '' || s === '—' ? r : `${r} (${s})`;
209
+ return s === '' || s === '—' ? r : `${r} (${escapeCell(s)})`;
195
210
  }
196
211
 
197
212
  /** Mirror `row(r)`. */
@@ -291,8 +291,8 @@ export interface CostBudgetConfig {
291
291
  readonly max_output_tokens: number;
292
292
  readonly max_calls: number;
293
293
  readonly max_total_usd: number;
294
- /** Rolling 24h cap. 0 disables it — and disabling it also disables the spend
295
- * ledger, since the orchestrator only appends an entry while a cap is live. */
294
+ /** Rolling 24h cap. 0 disables it. The spend ledger is written either way
295
+ * (ADR-279); this value decides only whether the total is compared. */
296
296
  readonly daily_limit_usd: number;
297
297
  }
298
298
 
@@ -1020,7 +1020,7 @@ function _build_debate(d: Dict): DebateConfig {
1020
1020
  if (!_isDict(d)) {
1021
1021
  throw new CouncilConfigError('`debate` must be a mapping.');
1022
1022
  }
1023
- const cap = _pyFloat(_get(d, 'max_cost_usd', 5.0));
1023
+ const cap = _pyFloat(_get(d, 'max_cost_usd', 0.0)); // 0 = no refusal cap (ADR-279)
1024
1024
  if (cap < 0) {
1025
1025
  throw new CouncilConfigError(
1026
1026
  `debate.max_cost_usd must be >= 0 (got ${_pyRepr(_f(cap))}; ` +
@@ -1671,10 +1671,10 @@ function _build_cost_budget(d: Dict): CostBudgetConfig {
1671
1671
  throw new CouncilConfigError('`cost_budget` must be a mapping.');
1672
1672
  }
1673
1673
  const cb: CostBudgetConfig = {
1674
- max_input_tokens: _pyInt(_get(d, 'max_input_tokens', 500_000)),
1675
- max_output_tokens: _pyInt(_get(d, 'max_output_tokens', 200_000)),
1676
- max_calls: _pyInt(_get(d, 'max_calls', 50)),
1677
- max_total_usd: _pyFloat(_get(d, 'max_total_usd', 20.0)),
1674
+ max_input_tokens: _pyInt(_get(d, 'max_input_tokens', 0)), // 0 = unbounded (ADR-279)
1675
+ max_output_tokens: _pyInt(_get(d, 'max_output_tokens', 0)), // 0 = unbounded (ADR-279)
1676
+ max_calls: _pyInt(_get(d, 'max_calls', 50)), // fan-out, not money — kept
1677
+ max_total_usd: _pyFloat(_get(d, 'max_total_usd', 0.0)), // 0 = unbounded (ADR-279)
1678
1678
  daily_limit_usd: _pyFloat(_get(d, 'daily_limit_usd', 0.0)),
1679
1679
  };
1680
1680
  const fields: Array<[keyof CostBudgetConfig, boolean]> = [