@event4u/agent-config 16.3.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 (486) 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 +251 -0
  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/estimate-ticket.md +1 -1
  16. package/dist/agent-src/commands/feature/explore.md +3 -3
  17. package/dist/agent-src/commands/feature/plan.md +1 -1
  18. package/dist/agent-src/commands/fix/ci.md +17 -3
  19. package/dist/agent-src/commands/fix/commit-messages.md +48 -23
  20. package/dist/agent-src/commands/fix/pr-comments.md +3 -6
  21. package/dist/agent-src/commands/implement-ticket.md +3 -3
  22. package/dist/agent-src/commands/memory/add.md +4 -16
  23. package/dist/agent-src/commands/memory/load.md +5 -6
  24. package/dist/agent-src/commands/memory/promote.md +3 -16
  25. package/dist/agent-src/commands/mission/upgrade.md +3 -2
  26. package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
  27. package/dist/agent-src/commands/optimize/deep.md +4 -2
  28. package/dist/agent-src/commands/optimize/rtk.md +4 -26
  29. package/dist/agent-src/commands/pr/create/description-only.md +18 -15
  30. package/dist/agent-src/commands/pr/create.md +42 -34
  31. package/dist/agent-src/commands/pr/merge.md +136 -9
  32. package/dist/agent-src/commands/prepare-for-review.md +13 -11
  33. package/dist/agent-src/commands/project/analyze.md +7 -35
  34. package/dist/agent-src/commands/refine-ticket.md +1 -1
  35. package/dist/agent-src/commands/review/changes.md +14 -19
  36. package/dist/agent-src/commands/roadmap/next.md +10 -1
  37. package/dist/agent-src/commands/roadmap/process-full.md +52 -38
  38. package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
  39. package/dist/agent-src/commands/worktree/create.md +7 -3
  40. package/dist/agent-src/commands/worktree/verify.md +2 -1
  41. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
  42. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
  43. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
  44. package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
  45. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
  46. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
  47. package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
  48. package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
  49. package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
  50. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
  51. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
  52. package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
  53. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
  54. package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
  55. package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
  56. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  57. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  58. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  59. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  60. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  61. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
  62. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  63. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  64. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
  65. package/dist/agent-src/guidelines/php/git.md +15 -2
  66. package/dist/agent-src/rules/active-remediation.md +0 -1
  67. package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
  68. package/dist/agent-src/rules/architecture.md +0 -1
  69. package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
  70. package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
  71. package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
  72. package/dist/agent-src/rules/autonomous-execution.md +0 -1
  73. package/dist/agent-src/rules/brand-consistency.md +0 -1
  74. package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
  75. package/dist/agent-src/rules/broken-access-control.md +0 -1
  76. package/dist/agent-src/rules/cli-output-handling.md +0 -1
  77. package/dist/agent-src/rules/code-comment-discipline.md +0 -1
  78. package/dist/agent-src/rules/code-provenance.md +0 -1
  79. package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
  80. package/dist/agent-src/rules/commit-conventions.md +1 -2
  81. package/dist/agent-src/rules/communication-through-line.md +1 -2
  82. package/dist/agent-src/rules/content-quoting-floor.md +1 -2
  83. package/dist/agent-src/rules/context-hygiene.md +5 -5
  84. package/dist/agent-src/rules/copilot-routing.md +1 -2
  85. package/dist/agent-src/rules/council-availability.md +4 -4
  86. package/dist/agent-src/rules/cross-source-consistency.md +4 -6
  87. package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
  88. package/dist/agent-src/rules/delegation-policy.md +2 -3
  89. package/dist/agent-src/rules/design-fidelity.md +0 -1
  90. package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
  91. package/dist/agent-src/rules/devcontainer-routing.md +1 -2
  92. package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
  93. package/dist/agent-src/rules/docker-commands.md +0 -1
  94. package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
  95. package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
  96. package/dist/agent-src/rules/domain-safety-pii.md +0 -1
  97. package/dist/agent-src/rules/domain-safety-retention.md +0 -1
  98. package/dist/agent-src/rules/downstream-changes.md +0 -1
  99. package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
  100. package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
  101. package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
  102. package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
  103. package/dist/agent-src/rules/finance-safety-floor.md +0 -1
  104. package/dist/agent-src/rules/fix-what-you-see.md +6 -32
  105. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
  106. package/dist/agent-src/rules/git-history-discipline.md +1 -2
  107. package/dist/agent-src/rules/guidelines.md +0 -1
  108. package/dist/agent-src/rules/history-discipline.md +0 -1
  109. package/dist/agent-src/rules/icon-consistency.md +0 -1
  110. package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
  111. package/dist/agent-src/rules/improve-before-implement.md +0 -1
  112. package/dist/agent-src/rules/invite-challenge.md +0 -1
  113. package/dist/agent-src/rules/laravel-routing.md +1 -2
  114. package/dist/agent-src/rules/laravel-translations.md +0 -1
  115. package/dist/agent-src/rules/legal-safety-floor.md +0 -1
  116. package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
  117. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
  118. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
  119. package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
  120. package/dist/agent-src/rules/media-governance-routing.md +1 -2
  121. package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
  122. package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
  123. package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
  124. package/dist/agent-src/rules/missing-tool-handling.md +0 -1
  125. package/dist/agent-src/rules/model-recommendation.md +0 -1
  126. package/dist/agent-src/rules/neighbour-precedence.md +64 -0
  127. package/dist/agent-src/rules/no-attribution-footers.md +0 -1
  128. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
  129. package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
  130. package/dist/agent-src/rules/no-roadmap-references.md +0 -1
  131. package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
  132. package/dist/agent-src/rules/onboarding-gate.md +0 -1
  133. package/dist/agent-src/rules/output-discipline.md +0 -1
  134. package/dist/agent-src/rules/package-ci-checks.md +0 -1
  135. package/dist/agent-src/rules/persona-governance.md +2 -3
  136. package/dist/agent-src/rules/php-coding.md +0 -1
  137. package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
  138. package/dist/agent-src/rules/preservation-guard.md +0 -1
  139. package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
  140. package/dist/agent-src/rules/question-not-instruction.md +0 -1
  141. package/dist/agent-src/rules/reviewer-awareness.md +0 -1
  142. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
  143. package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
  144. package/dist/agent-src/rules/role-mode-adherence.md +0 -1
  145. package/dist/agent-src/rules/rule-type-governance.md +0 -1
  146. package/dist/agent-src/rules/runtime-safety.md +0 -1
  147. package/dist/agent-src/rules/scale-discipline.md +0 -1
  148. package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
  149. package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
  150. package/dist/agent-src/rules/self-repair-loop.md +0 -1
  151. package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
  152. package/dist/agent-src/rules/session-canary.md +0 -1
  153. package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
  154. package/dist/agent-src/rules/size-enforcement.md +0 -1
  155. package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
  156. package/dist/agent-src/rules/skill-quality.md +0 -1
  157. package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
  158. package/dist/agent-src/rules/source-confidentiality.md +0 -1
  159. package/dist/agent-src/rules/source-discovery-gate.md +0 -1
  160. package/dist/agent-src/rules/source-of-truth.md +0 -1
  161. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
  162. package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
  163. package/dist/agent-src/rules/symfony-routing.md +1 -2
  164. package/dist/agent-src/rules/think-before-action.md +0 -1
  165. package/dist/agent-src/rules/token-budget-discipline.md +12 -46
  166. package/dist/agent-src/rules/token-efficiency.md +0 -1
  167. package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
  168. package/dist/agent-src/rules/tool-safety.md +0 -1
  169. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  170. package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
  171. package/dist/agent-src/rules/upstream-proposal.md +0 -1
  172. package/dist/agent-src/rules/user-interaction.md +0 -1
  173. package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
  174. package/dist/agent-src/scripts/gate_budget.ts +47 -23
  175. package/dist/agent-src/scripts/gate_execute.ts +12 -4
  176. package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
  177. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
  178. package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
  179. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
  180. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  181. package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
  182. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
  183. package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
  184. package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
  185. package/dist/agent-src/skills/database/data/manifest.json +2 -2
  186. package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
  187. package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
  188. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  189. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  190. package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
  191. package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
  192. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
  193. package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
  194. package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
  195. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  196. package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
  197. package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
  198. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
  199. package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
  200. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
  201. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  202. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  203. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  204. package/dist/agent-src/templates/AGENTS.md +1 -1
  205. package/dist/agent-src/templates/agent-settings.md +46 -129
  206. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
  207. package/dist/agent-src/templates/command.md +2 -2
  208. package/dist/agent-src/templates/roadmaps.md +6 -1
  209. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  210. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  211. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  212. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  213. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  214. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  215. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  216. package/dist/agent-src/templates/skill.md +1 -1
  217. package/dist/cli/registry.js +1 -0
  218. package/dist/cli-delegate/check_update_banner.js +195 -119
  219. package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
  220. package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
  221. package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
  222. package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
  223. package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
  224. package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-AED2VQGM.js} +65 -11
  225. package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
  226. package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
  227. package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
  228. package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
  229. package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
  230. package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
  231. package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
  232. package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
  233. package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
  234. package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-MSUL5NYP.js} +5 -5
  235. package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
  236. package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
  237. package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
  238. package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
  239. package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
  240. package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
  241. package/dist/cli-delegate/cmd_analyze_session.js +223 -43
  242. package/dist/cli-delegate/cmd_brand_status.js +3 -2
  243. package/dist/cli-delegate/cmd_conformance.js +105 -35
  244. package/dist/cli-delegate/cmd_converge.js +3 -3
  245. package/dist/cli-delegate/cmd_doctor.js +15 -12
  246. package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
  247. package/dist/cli-delegate/cmd_explain.js +43 -19
  248. package/dist/cli-delegate/cmd_export.js +10 -10
  249. package/dist/cli-delegate/cmd_git_convention.js +1851 -0
  250. package/dist/cli-delegate/cmd_handoff.js +40 -21
  251. package/dist/cli-delegate/cmd_mcp_available.js +3 -2
  252. package/dist/cli-delegate/cmd_migrate.js +3 -3
  253. package/dist/cli-delegate/cmd_packs_active.js +4 -3
  254. package/dist/cli-delegate/cmd_prune.js +10 -10
  255. package/dist/cli-delegate/cmd_route_audit.js +7 -7
  256. package/dist/cli-delegate/cmd_route_explain.js +5 -5
  257. package/dist/cli-delegate/cmd_session_recycle.js +9 -7
  258. package/dist/cli-delegate/cmd_settings_check.js +54 -7
  259. package/dist/cli-delegate/cmd_settings_get.js +18 -8
  260. package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
  261. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  262. package/dist/cli-delegate/cmd_sync.js +10 -10
  263. package/dist/cli-delegate/cmd_uninstall.js +10 -10
  264. package/dist/cli-delegate/cmd_update.js +7 -7
  265. package/dist/cli-delegate/cmd_upgrade.js +7 -7
  266. package/dist/cli-delegate/cmd_validate.js +10 -10
  267. package/dist/cli-delegate/cmd_versions.js +5 -5
  268. package/dist/cli-delegate/gate_budget.js +1 -1
  269. package/dist/cli-delegate/gate_execute.js +2 -2
  270. package/dist/cli-delegate/roadmap_gates.js +2 -2
  271. package/dist/discovery/deprecation-report.md +1 -1
  272. package/dist/discovery/discovery-manifest.json +129 -90
  273. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  274. package/dist/discovery/discovery-manifest.summary.md +3 -3
  275. package/dist/discovery/dormancy-report.md +1 -1
  276. package/dist/discovery/orphan-report.md +1 -1
  277. package/dist/discovery/packs.json +24 -9
  278. package/dist/discovery/trust-report.md +3 -3
  279. package/dist/discovery/workspaces.json +5 -4
  280. package/dist/hooks/dispatch.js +2151 -1820
  281. package/dist/hooks/dispatch.sha256 +1 -1
  282. package/dist/install/install.mjs +462 -431
  283. package/dist/install/installThinLayer.js +40 -12
  284. package/dist/install/installedRuleLinks.js +105 -19
  285. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  286. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
  287. package/dist/mcp/registry-manifest.json +5 -5
  288. package/dist/mcp/server.json +2 -2
  289. package/dist/mcp/server.mjs +2702 -1995
  290. package/dist/router.json +1 -1
  291. package/dist/scripts/_lib/agent_settings.js +15 -120
  292. package/dist/scripts/_lib/compile_time_toggles.js +12 -21
  293. package/dist/scripts/_lib/git_convention.js +232 -0
  294. package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
  295. package/dist/scripts/_lib/installed_layer.js +344 -18
  296. package/dist/scripts/_lib/package_root.js +68 -0
  297. package/dist/scripts/_lib/rule_law_section.js +1 -1
  298. package/dist/scripts/_lib/settings_removed_keys.js +168 -0
  299. package/dist/scripts/_lib/thin_rules.js +80 -3
  300. package/dist/server/app.js +2 -1
  301. package/dist/server/gitKeysGate.js +105 -0
  302. package/dist/server/routes/settings.js +67 -8
  303. package/dist/server/routes/wizard.js +4 -0
  304. package/dist/server/schemas/settings.js +23 -81
  305. package/dist/shared/skillRanking.js +30 -4
  306. package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
  307. package/dist/ui/index.html +1 -1
  308. package/docs/MIGRATION.md +72 -1
  309. package/docs/contracts/settings-classes.md +35 -65
  310. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  311. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  312. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  313. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  314. package/docs/guidelines/agent-infra/layered-settings.md +13 -1
  315. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  316. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  317. package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
  318. package/docs/guidelines/php/git.md +15 -2
  319. package/package.json +1 -1
  320. package/src/agent-src/scripts/gate_budget.ts +47 -23
  321. package/src/agent-src/scripts/gate_execute.ts +12 -4
  322. package/src/agent-src/templates/AGENTS.md +1 -1
  323. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  324. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  325. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  326. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  327. package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  328. package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  329. package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  330. package/src/config/agent-settings.template.yml +79 -312
  331. package/src/config/agents-paths.yml +16 -0
  332. package/src/config/assurance-capability-registry.json +7 -3
  333. package/src/config/ci-local-parity.yml +3 -0
  334. package/src/config/continuity-surface.json +3 -3
  335. package/src/config/discovery/packs.yml +17 -1
  336. package/src/config/evaluator-budgets.json +19 -6
  337. package/src/config/gate-coverage.yml +65 -23
  338. package/src/config/gate-violation-baselines.json +53 -13
  339. package/src/config/gitignore-block.txt +19 -0
  340. package/src/config/hook-bundle-budget.json +1 -1
  341. package/src/config/release-gate-locality.yml +2 -1
  342. package/src/config/routing-coverage-seed.json +48 -6
  343. package/src/config/rule-law-ceilings.json +12 -6
  344. package/src/config/rule-obligations.json +833 -0
  345. package/src/install/installThinLayer.ts +76 -10
  346. package/src/install/installedRuleLinks.ts +105 -17
  347. package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
  348. package/src/scripts/_cli/cmd_conformance.ts +13 -2
  349. package/src/scripts/_cli/cmd_doctor.ts +10 -10
  350. package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
  351. package/src/scripts/_cli/cmd_explain.ts +72 -14
  352. package/src/scripts/_cli/cmd_git_convention.ts +637 -0
  353. package/src/scripts/_cli/cmd_settings_check.ts +66 -8
  354. package/src/scripts/_cli/cmd_settings_get.ts +18 -3
  355. package/src/scripts/_cli/doctor_execution.ts +72 -1
  356. package/src/scripts/_dispatch.bash +37 -2
  357. package/src/scripts/_lib/agent_settings.ts +15 -124
  358. package/src/scripts/_lib/blocked_by_marker.ts +1 -1
  359. package/src/scripts/_lib/compile_time_toggles.ts +12 -21
  360. package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
  361. package/src/scripts/_lib/git_base_ref.ts +92 -0
  362. package/src/scripts/_lib/git_convention.ts +291 -0
  363. package/src/scripts/_lib/git_convention_carrier.ts +389 -0
  364. package/src/scripts/_lib/git_convention_grammar.ts +246 -0
  365. package/src/scripts/_lib/git_convention_measure.ts +344 -0
  366. package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
  367. package/src/scripts/_lib/graph_feeder_record.ts +236 -13
  368. package/src/scripts/_lib/installed_layer.ts +448 -23
  369. package/src/scripts/_lib/knowledge_global.ts +14 -1
  370. package/src/scripts/_lib/module_reach.ts +456 -0
  371. package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
  372. package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
  373. package/src/scripts/_lib/ratification_artifact.ts +220 -1
  374. package/src/scripts/_lib/ratification_subject.ts +92 -0
  375. package/src/scripts/_lib/release_findings_ingest.ts +15 -7
  376. package/src/scripts/_lib/release_highlights.ts +5 -0
  377. package/src/scripts/_lib/rule_law_section.ts +1 -1
  378. package/src/scripts/_lib/rule_obligations.ts +205 -0
  379. package/src/scripts/_lib/self_repair.ts +1 -1
  380. package/src/scripts/_lib/settings_removed_keys.ts +173 -0
  381. package/src/scripts/_lib/test_red_state.ts +5 -0
  382. package/src/scripts/_lib/thin_rules.ts +83 -3
  383. package/src/scripts/_lib/touched_file_quality.ts +142 -6
  384. package/src/scripts/_lib/worker_budget.ts +1 -1
  385. package/src/scripts/adr/regenerate_index.ts +16 -1
  386. package/src/scripts/ai_council/config.ts +7 -7
  387. package/src/scripts/ai_council/modification_review.ts +100 -0
  388. package/src/scripts/ai_council/modification_review_questions.ts +90 -0
  389. package/src/scripts/ai_council/orchestrator.ts +5 -5
  390. package/src/scripts/ai_council/spend_gate.ts +18 -7
  391. package/src/scripts/ai_team/config.ts +11 -16
  392. package/src/scripts/audit_user_type_axis.ts +20 -8
  393. package/src/scripts/bench_ab_clone.ts +1 -2
  394. package/src/scripts/bench_concern_spawn_path.ts +129 -0
  395. package/src/scripts/bench_graph_feeder_latency.ts +584 -0
  396. package/src/scripts/check_agent_artifact_location.ts +36 -0
  397. package/src/scripts/check_branch_freshness.ts +147 -24
  398. package/src/scripts/check_enforcement_coverage.ts +130 -0
  399. package/src/scripts/check_evaluator_budgets.ts +4 -0
  400. package/src/scripts/check_finding_dispositions.ts +88 -25
  401. package/src/scripts/check_gate_coverage.ts +4 -3
  402. package/src/scripts/check_gate_reachability.ts +48 -1
  403. package/src/scripts/check_generator_sync.ts +48 -0
  404. package/src/scripts/check_hook_bundle_composition.ts +107 -0
  405. package/src/scripts/check_kernel_edit_ratified.ts +86 -6
  406. package/src/scripts/check_pack_size.ts +1 -1
  407. package/src/scripts/check_release_manifest_content.ts +189 -0
  408. package/src/scripts/check_standing_rule_delivery.ts +96 -0
  409. package/src/scripts/check_suppression_hygiene.ts +2 -5
  410. package/src/scripts/ci_settle.ts +42 -5
  411. package/src/scripts/classify_merge_risk.ts +320 -0
  412. package/src/scripts/closure_scan.ts +91 -1
  413. package/src/scripts/command_suggester/settings.ts +8 -108
  414. package/src/scripts/command_suggester/types.ts +4 -5
  415. package/src/scripts/consumer_matrix.ts +102 -0
  416. package/src/scripts/context_hygiene_hook.ts +13 -23
  417. package/src/scripts/cost/preflight.mjs +12 -1
  418. package/src/scripts/council_cli.ts +7 -7
  419. package/src/scripts/dispatch_r2_reviewer.ts +24 -11
  420. package/src/scripts/explain_run.ts +8 -13
  421. package/src/scripts/generate_git_convention_grammar.ts +127 -0
  422. package/src/scripts/generate_host_cost_table.ts +20 -3
  423. package/src/scripts/handoff_context_hook.ts +86 -37
  424. package/src/scripts/hook_manifest.json +1 -1
  425. package/src/scripts/hook_manifest.yaml +25 -6
  426. package/src/scripts/hooks/block_config_weakening.ts +48 -5
  427. package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
  428. package/src/scripts/hooks/concern_registry.ts +2 -0
  429. package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
  430. package/src/scripts/hooks/evidence_independence.ts +12 -4
  431. package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
  432. package/src/scripts/hooks/push_settle_hook.ts +4 -3
  433. package/src/scripts/hooks/rule_inject_hook.ts +44 -3
  434. package/src/scripts/hooks/state_io.ts +8 -4
  435. package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
  436. package/src/scripts/hooks/turn_end_gate_hook.ts +1 -0
  437. package/src/scripts/install-hooks.sh +42 -14
  438. package/src/scripts/install.ts +7 -31
  439. package/src/scripts/lint_blocker_citations.ts +198 -0
  440. package/src/scripts/lint_evidence_artifacts.ts +9 -0
  441. package/src/scripts/lint_hook_concern_budget.ts +10 -21
  442. package/src/scripts/lint_pack_boundaries.ts +406 -28
  443. package/src/scripts/lint_roadmap_blockers.ts +282 -29
  444. package/src/scripts/lint_roadmap_complexity.ts +4 -2
  445. package/src/scripts/lint_rule_law_section.ts +151 -21
  446. package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
  447. package/src/scripts/lint_settings_classes.ts +1 -1
  448. package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
  449. package/src/scripts/lint_workflow_security.ts +12 -1
  450. package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
  451. package/src/scripts/model_rule_injection.ts +3 -3
  452. package/src/scripts/onboarding_gate_hook.ts +7 -6
  453. package/src/scripts/print_required_checks.ts +15 -3
  454. package/src/scripts/probe_host_compliance.ts +33 -5
  455. package/src/scripts/probe_turnaround.ts +183 -3
  456. package/src/scripts/ratification_header.ts +77 -0
  457. package/src/scripts/refusal_envelope.ts +138 -0
  458. package/src/scripts/release_publication.ts +29 -3
  459. package/src/scripts/report_dispatch_import_closure.ts +76 -0
  460. package/src/scripts/report_installed_rule_links.ts +118 -1
  461. package/src/scripts/report_module_reach.ts +212 -0
  462. package/src/scripts/report_obligation_mechanism.ts +16 -18
  463. package/src/scripts/report_parked_blockers.ts +222 -0
  464. package/src/scripts/report_required_checks_drift.ts +196 -0
  465. package/src/scripts/report_skill_ranker_confusion.ts +103 -2
  466. package/src/scripts/report_standing_payload_by_host.ts +1 -1
  467. package/src/scripts/routing_doctor.ts +2 -2
  468. package/src/scripts/schemas/agent-settings.schema.json +17 -31
  469. package/src/scripts/schemas/command.schema.json +1 -1
  470. package/src/scripts/schemas/skill.schema.json +1 -1
  471. package/src/scripts/self_review_gate.ts +39 -2
  472. package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
  473. package/src/scripts/sync_pr_branch.ts +403 -132
  474. package/src/scripts/trigger_eval_grandfather.json +0 -16
  475. package/src/server/schemas/settings.ts +33 -177
  476. package/src/shared/skillRanking.ts +53 -4
  477. package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
  478. package/src/scripts/_lib/config_chain.ts +0 -477
  479. package/src/scripts/_lib/conformance_report.ts +0 -403
  480. package/src/scripts/_lib/eval_discrimination.ts +0 -95
  481. package/src/scripts/_lib/evaluator_promotion.ts +0 -225
  482. package/src/scripts/_lib/file_slicer.ts +0 -117
  483. package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
  484. package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
  485. package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
  486. package/src/scripts/_lib/role_split.ts +0 -338
@@ -0,0 +1,168 @@
1
+ /**
2
+ * The registry of DELETED settings keys, and the once-per-run notice a leftover
3
+ * value gets. Extracted from `agent_settings.ts`, which sits at the 1500-line
4
+ * source ceiling — every retirement batch adds entries here, and here they cost
5
+ * no ratchet. `agent_settings.ts` re-exports `REMOVED_KEYS` so existing
6
+ * importers (the loader, `lint_settings_classes`) are unchanged.
7
+ */
8
+ /**
9
+ * Settings keys this package has DELETED. A leftover value from an older
10
+ * install is ignored — never applied by any reader — and surfaced with ONE
11
+ * deprecation line per key per process run (stderr; the exit code never
12
+ * changes).
13
+ *
14
+ * The map carries a per-key REASON rather than one shared sentence, because
15
+ * the list now spans more than one deletion doctrine and a single blanket
16
+ * phrase would mis-attribute every future entry. A reader who hits the line
17
+ * should learn why the key went, not just that it did.
18
+ *
19
+ * `subagents.*` — the always-on-orchestration doctrine
20
+ * (road-to-always-on-orchestration Phase 1): the layer has no per-layer
21
+ * on/off setting any more. `ai_team.enabled` joined in Step 1.3 — the
22
+ * `/team` family's availability is a codex-CLI/auth FACT
23
+ * (`src/scripts/ai_team/availability.ts`), not a flag; the `ai_team` config
24
+ * loader (`src/scripts/ai_team/config.ts`) separately accepts a leftover
25
+ * `enabled` key without failing closed, so this warning is the only surfaced
26
+ * signal of that deletion.
27
+ *
28
+ * `hooks.turn_end_gate.*` — the turn-end gate is always armed (2026-08-12).
29
+ * A default-off safety gate cannot soak, so the switch protecting the soak
30
+ * made the soak impossible; whether the gate fires is now decided by each
31
+ * detector's own trigger conditions. See `turn_end_gate_hook.ts` § "Always
32
+ * armed".
33
+ *
34
+ * The five `derivable` leaves below (2026-08-12, road-to-zero-settings Phase
35
+ * 2.1) are a different case from every entry above them, and the difference is
36
+ * the whole safety argument: no code path ever *consulted* them. Each appeared
37
+ * in the template, the schema and the reference page, and several in the setup
38
+ * wizard, while the decision they looked like they governed was taken
39
+ * elsewhere. A key nothing reads cannot change a default by leaving — so this
40
+ * is the one deletion batch that needs no replacement mechanism, only the
41
+ * per-key statement of what already decides.
42
+ *
43
+ * A sixth unread key, `screenshots.data_bearing_gate`, was found in the same
44
+ * pass and deliberately NOT deleted — it is `consent`, and the open question is
45
+ * whether the repair is to build its missing reader or to delete a promise a
46
+ * Hard Floor can never honour. See `settings-classes.md` § The six unread keys.
47
+ *
48
+ * `worktrees.mode` (2026-08-13, ADR-229) is a third doctrine again: not
49
+ * always-on, not unread. It WAS read, and the reader honoured all three values —
50
+ * the deletion says the decision was never the agent's to make. `ask` bought a
51
+ * round trip per spawn, `on` let the agent start parallel work unprompted, and
52
+ * `off` described the wanted behavior, so `off` became the hardcoded rule and
53
+ * the switch went. What decides instead is the user's own sentence in the chat.
54
+ *
55
+ * The 2026-10-09 batch (road-to-settings-classes-derivable-surface-stagnation
56
+ * Phase 2) is a fourth doctrine: `derivable` keys whose shipped default is the
57
+ * only behavior the package supports. Each WAS read — by code or by rule and
58
+ * command prose — and every reader was rewritten to state the old default as
59
+ * fixed behavior in the same change, so retiring the key changes no effective
60
+ * default; what a consumer who had set a non-default value loses is named by
61
+ * the reason.
62
+ *
63
+ * Every reason string must name what decides INSTEAD, never just "removed".
64
+ * Exported so `lint_settings_classes` can check the deletion side of the
65
+ * surface: a reason that names no replacement, or an entry whose key is live in
66
+ * the template again, is a contradiction the loader itself cannot notice.
67
+ */
68
+ export const REMOVED_KEYS = new Map([
69
+ ['subagents.enabled', 'always-on orchestration'],
70
+ ['subagents.auto', 'always-on orchestration'],
71
+ ['subagents.host_capabilities', 'always-on orchestration'],
72
+ ['subagents.budget_routing', 'always-on orchestration'],
73
+ ['ai_team.enabled', 'always-on orchestration'],
74
+ ['hooks.turn_end_gate.enabled', 'the turn-end gate is always armed'],
75
+ ['hooks.turn_end_gate.promissory', 'the turn-end gate is always armed'],
76
+ ['hooks.turn_end_gate.language', 'the turn-end gate is always armed'],
77
+ ['hooks.turn_end_gate.verification', 'the turn-end gate is always armed'],
78
+ ['telegraph.speak_scope', 'the rule body states its own scope; compile_time_toggles decides whether the rule ships'],
79
+ ['chat_history.max_size_kb', 'the rotate command takes --max-kb from argv; session-count pruning bounds the file'],
80
+ ['chat_history.on_overflow', 'the overflow mode comes from the rotate command --mode argv'],
81
+ ['quality.wait_for_remote_ci', 'whether to poll follows from the push plus a detectable remote pipeline'],
82
+ ['legal_review_prep.consented_at', 'the provenance sidecar settings:set writes and consentVerdict reads'],
83
+ ['worktrees.mode', 'the user asking for a worktree in the chat; creation is instruction-only and hardcoded'],
84
+ // 2026-10-09 — output and tone
85
+ ['personal.minimal_output', 'direct-answers Iron Law 3 mandates terse replies; there is no verbose mode'],
86
+ ['personal.play_by_play', 'direct-answers: no narration unless the user asks for it in the turn'],
87
+ ['personal.pr_comment_bot_icon', 'no-decorative-emojis-in-git-surfaces forbids the 🤖 prefix'],
88
+ ['verbosity.intent_announcements', 'direct-answers: act and emit the result, no "Let me…" openers'],
89
+ ['verbosity.preview_artifacts', 'generated content is used directly; preview-on-error and the Iron-Law gates decide when a preview shows'],
90
+ ['verbosity.routine_confirmations', 'the no-cheap-questions Pre-Send Self-Check; Iron-Law gates always ask'],
91
+ ['verbosity.post_action_reports', 'direct-answers Iron Law 3: a one-line confirmation and one end-summary'],
92
+ ['telegraph.speak', 'the telegraph-speak predicate in compile_time_toggles.ts; the bench verdict is package-level (ADR telegraph/0002)'],
93
+ ['tokens.rich_skills', "the skill's own token_budget_class: rich plus the lint_token_budget_discipline ceiling"],
94
+ // 2026-10-09 — reasoning protocol switches
95
+ ['reasoning.auto_gate', 'the RDP gate task signal plus the host self-assessment in rdp-gate.md'],
96
+ ['reasoning.components.orchestrator', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
97
+ ['reasoning.components.notes_first', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
98
+ ['reasoning.components.grounding', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
99
+ ['reasoning.components.intent', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
100
+ ['reasoning.components.complexity_first', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
101
+ ['reasoning.components.verifier_default', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
102
+ ['reasoning.components.prediction_tracking', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
103
+ ['reasoning.components.decision_ledger', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
104
+ ['reasoning.components.uncertainty_budget', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
105
+ // 2026-10-09 — roadmap cadence
106
+ ['roadmap.skip_pre_run_gate', 'the command name names the scope; only an ambiguous roadmap or an unresolvable conflict shows the gate'],
107
+ ['roadmap.dashboard_regen_cadence', 'a fixed cadence: every 5th closed step, every phase boundary, reply end and any file-shape touch'],
108
+ // 2026-10-09 — command suggestion and PR creation
109
+ ['commands.auto_detect', "an orchestrator's own auto_detect front-matter and the --no-auto-detect flag"],
110
+ ['commands.suggestion.enabled', 'the suggester match-score floor and cooldown; /command-suggestion-off silences one conversation'],
111
+ ['commands.suggestion.confidence_floor', "the suggester's fixed 0.6 floor; a command's own suggestion frontmatter can tighten it"],
112
+ ['commands.suggestion.cooldown_seconds', "the suggester's fixed 600-second cooldown; a command's own suggestion frontmatter can lengthen it"],
113
+ ['commands.suggestion.max_options', 'the fixed cap of 4 suggestions plus the always-present as-is option'],
114
+ ['commands.create_pr.api_examples', "/create-pr's grounding rule: an example only from a real source, otherwise a one-line pointer"],
115
+ ['commands.create_pr.ui_paths', "/create-pr's light frontend heuristic, which fails open"],
116
+ ['commands.create_pr.api_paths', "/create-pr's light API-endpoint heuristic, which fails open"],
117
+ // 2026-10-09 — memory and knowledge sharing
118
+ ['memory.cadence', 'a fixed cadence: the memory line renders whenever a memory type was asked; memory.visibility: off still silences it'],
119
+ ['memory.review_threshold', "/memory load's fixed preview threshold of 10 unreviewed intake signals"],
120
+ ['knowledge.global_sharing.redaction.enabled', 'the write-time redaction scan, which always runs before a card goes global'],
121
+ ['knowledge.global_sharing.redaction.halt_on_trigger', 'the redaction gate, which always halts on a confidential-pattern hit'],
122
+ ['knowledge.global_sharing.auto_promote_threshold', 'the fixed two-repo sighting count that triggers a promotion suggestion'],
123
+ ['knowledge.global_sharing.freshness.hypothesis_after_days', "the card's age over last_verified against the fixed 90-day lead-only window"],
124
+ ['knowledge.global_sharing.freshness.stale_after_days', "the card's age over last_verified against the fixed 180-day skip window"],
125
+ // 2026-10-09 — hooks and engine
126
+ ['hooks.concern_budget.max_per_event', "the concern-budget gate's own constant of 8 per (platform, event) cell"],
127
+ ['hooks.concern_budget.hard_fail', "the concern-budget gate's --strict argv; without it the gate warns"],
128
+ ['decision_engine.surface_traces', 'nothing: the per-phase decision trace stays off, the old default'],
129
+ ['decision_engine.on_block_fallback', 'the fail-safe: an on_block ask that times out always stops'],
130
+ ['explain.enable_last', 'the presence of a work-state trace; explain last always renders it'],
131
+ // 2026-10-09 — remaining
132
+ ['project.pr_template', '/create-pr, which reads .github/pull_request_template.md'],
133
+ ['pipelines.skill_improvement', 'the skill-improvement-trigger rule; the capture is a proposal the user confirms'],
134
+ ['consistency.cross_source', 'the cross-source-consistency rule, always on; batching and the no-cheap-questions floor bound the noise'],
135
+ ['subagents.downshift', 'the model_tier each sub-task declares; downshift is always on'],
136
+ ['ai_team.suppress_setup_hint', 'nothing: the one-line team-mode setup hint is always shown'],
137
+ ]);
138
+ /** Keys already warned about in THIS process — the "once per run" dedupe. */
139
+ const _warnedRemovedKeys = new Set();
140
+ /** Read one dotted path out of a merged settings tree; `undefined` when absent. */
141
+ function _readDotted(root, dotted) {
142
+ let node = root;
143
+ for (const part of dotted.split('.')) {
144
+ if (typeof node !== 'object' || node === null || Array.isArray(node)) {
145
+ return undefined;
146
+ }
147
+ node = node[part];
148
+ }
149
+ return node;
150
+ }
151
+ /**
152
+ * Warn once per process, on stderr, for every {@link REMOVED_KEYS} entry still
153
+ * present in a resolved settings tree. Never throws, never changes what the
154
+ * caller does with `merged` — a pure notification side effect.
155
+ */
156
+ export function warnRemovedKeys(merged) {
157
+ for (const [key, reason] of REMOVED_KEYS) {
158
+ if (_warnedRemovedKeys.has(key)) {
159
+ continue;
160
+ }
161
+ if (_readDotted(merged, key) === undefined) {
162
+ continue;
163
+ }
164
+ _warnedRemovedKeys.add(key);
165
+ process.stderr.write(`${key} was removed (${reason}); ignored.\n`);
166
+ }
167
+ }
168
+ //# sourceMappingURL=settings_removed_keys.js.map
@@ -255,13 +255,90 @@ function _title(s) {
255
255
  * Exported so the WRITER and every DETECTOR share one definition. A gate that
256
256
  * re-spelled this string would drift from the writer silently, and the failure
257
257
  * would be invisible in exactly the direction that matters: a stub the gate
258
- * fails to recognise reads as a complete rule body.
258
+ * fails to recognise reads as a complete rule body. Two gates had done exactly
259
+ * that until step 2.1 of `road-to-a-thinned-layer-measured-in-one-unit`; both
260
+ * import this now.
261
+ *
262
+ * SHORTENED 2026-10-06 from 47 characters to 27 (step 2.2). It is paid once per
263
+ * stub and there were 89 stubs on the measured layer, so the sentence cost
264
+ * 4,183 characters of a 97,496-character standing total; at 27 it costs 2,403,
265
+ * a saving of 1,780 = 20 x 89.
266
+ *
267
+ * WHAT THE SHORTENING WAS NOT ALLOWED TO DO: drop the instruction. This is the
268
+ * only standing text in the whole layer that says what a stub is FOR — "load
269
+ * the body" occurs in no kernel rule and in neither root instruction file — so
270
+ * a bare token like `> thin` would have saved more and left nothing that could
271
+ * be followed. The decision record (D2, K6) rejected that explicitly: nothing
272
+ * in this repository can check whether an instruction nobody states is still
273
+ * obeyed.
274
+ *
275
+ * WHY IT MUST STAY LONG ENOUGH TO BE UNIQUE: {@link is_thin_entry} is a
276
+ * substring test over the whole file, so a marker short or generic enough to
277
+ * occur inside ordinary rule prose would make that rule read as a stub — and
278
+ * nine rule files carry blockquote lines. `thin_marker_unique_in_corpus.test.ts`
279
+ * runs the constant against every rule body in `src/rules/` and against every
280
+ * entry `build_thin` emits, in both directions, which is the check that bounds
281
+ * any further shortening.
259
282
  */
260
- export const THIN_ENTRY_MARKER = '> Routed rule — load the body on trigger-match.';
283
+ export const THIN_ENTRY_MARKER = '> Load the body on a match.';
261
284
  /** Is this projected entry a pointer stub rather than a rule body? */
262
285
  export function is_thin_entry(text) {
263
286
  return text.includes(THIN_ENTRY_MARKER);
264
287
  }
288
+ /**
289
+ * What introduces a stub's body pointer. One writer, one reader.
290
+ *
291
+ * A BARE PATH SINCE 2026-10-06 (step 2.3 of
292
+ * `road-to-a-thinned-layer-measured-in-one-unit`). The pointer used to be a
293
+ * markdown link, ``Body: [`<id>`](<prefix><id>.md)``, whose link TEXT repeated
294
+ * the rule id the target already ends in. That cost `6 + len(id)` per stub over
295
+ * the bare form — 2,359 characters across the 89 stubs of the measured layer,
296
+ * 534 of it pure syntax and the rest the id written a second time.
297
+ *
298
+ * Nothing followed the link as a link. Under `delivery` the hook loads the body
299
+ * and never reads the pointer at all; under `thin` an agent reads the path. A
300
+ * markdown link renders in neither case, so the syntax bought rendering nobody
301
+ * was doing.
302
+ */
303
+ export const THIN_BODY_POINTER_PREFIX = 'Body: ';
304
+ /**
305
+ * The pointer, as the WRITER emits it — exported so a detector cannot re-spell
306
+ * it, which is the same drift {@link THIN_ENTRY_MARKER} documents one screen up
307
+ * and which two gates had already committed there.
308
+ *
309
+ * WHAT IT CAPTURES is the whole tail of the line from `Body: ` to its end, and
310
+ * that is the intended semantic rather than an accident of greediness: the
311
+ * writer emits the pointer LAST on its line, so the tail IS the path. A review
312
+ * round proposed a lazy `(.+?\.md)` to stop at the first `.md`; measured, it
313
+ * changes nothing, because `\s*$` forces the match to reach end of line either
314
+ * way and a lazy quantifier simply backtracks forward to the same place. The
315
+ * greedy form is kept and the property is pinned by a test, so the next reader
316
+ * meets the measurement instead of repeating the proposal.
317
+ *
318
+ * ANCHORED TO END OF LINE, NOT `\S+`. The pointer is the last thing on its
319
+ * line, and a package root may contain spaces; `\S+` would silently stop at the
320
+ * first one and report a well-formed pointer as missing.
321
+ *
322
+ * COMPOSED FROM {@link THIN_BODY_POINTER_PREFIX} rather than re-spelling it.
323
+ * The constant exists so a reader cannot hold its own copy, and a pattern six
324
+ * lines below it holding a literal `Body: ` would have broken that invariant in
325
+ * the file that states it.
326
+ */
327
+ export const THIN_BODY_POINTER_RE = (() => {
328
+ const lit = THIN_BODY_POINTER_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
329
+ // THE LAST PREFIX ON THE LINE, NOT THE FIRST. `thin_entry` puts the rule's
330
+ // own `description` on the SAME line ahead of the pointer, so a description
331
+ // containing the literal `Body: ` used to start the match inside the
332
+ // description and capture it as part of the path — `has_body_pointer` stayed
333
+ // true while the extraction was wrong, which is a wrong assertion rather
334
+ // than a visible failure. Forbidding a second prefix inside the capture
335
+ // makes the first viable start the last occurrence, which is the pointer.
336
+ return new RegExp(`${lit}((?:(?!${lit}).)+\\.md)\\s*$`, 'm');
337
+ })();
338
+ /** Does this entry carry a body pointer the writer would recognise? */
339
+ export function has_body_pointer(text) {
340
+ return THIN_BODY_POINTER_RE.test(text);
341
+ }
265
342
  /**
266
343
  * Where a stub tells a reader the body actually is.
267
344
  *
@@ -318,7 +395,7 @@ export function thin_entry(rule_id, text, bodyLinkPrefix = BODY_LINK_PREFIX) {
318
395
  const fires = hint ? ` Fires on: ${hint}.` : '';
319
396
  return (`## ${title}\n` +
320
397
  `${THIN_ENTRY_MARKER}${fires} ${desc} ` +
321
- `Body: [\`${rule_id}\`](${bodyLinkPrefix}${rule_id}.md)\n`);
398
+ `${THIN_BODY_POINTER_PREFIX}${bodyLinkPrefix}${rule_id}.md\n`);
322
399
  }
323
400
  /**
324
401
  * The marker that opens a stub's copied law block, and the one that closes it
@@ -155,7 +155,7 @@ export async function createApp(opts) {
155
155
  await app.register(pingRoute({ writeRoot, projectScopeRoot, mode, dryRun, projectSurface: opts.projectSurface === true }));
156
156
  await app.register(discoveryRoute(opts.discoveryManifestPath ? { manifestPath: opts.discoveryManifestPath } : {}));
157
157
  await app.register(schemaRoute());
158
- await app.register(settingsRoute({ writeRoot, legacyReadRoot, packageRoot, dryRun, userGlobalReadRoot: userGlobalRead }));
158
+ await app.register(settingsRoute({ writeRoot, legacyReadRoot, packageRoot, dryRun, userGlobalReadRoot: userGlobalRead, userGlobalWrite: mode === 'global' }));
159
159
  await app.register(settingsChangesRoute({ writeRoot, userGlobalReadRoot: userGlobalRead, dryRun }));
160
160
  await app.register(userMdRoute({ writeRoot, legacyReadRoot, dryRun, userGlobalReadRoot: userGlobalRead }));
161
161
  await app.register(installRoute(opts.installRouteOptions ?? {}));
@@ -167,6 +167,7 @@ export async function createApp(opts) {
167
167
  dryRun,
168
168
  userGlobalReadRoot: userGlobalRead,
169
169
  extendedSteps: opts.extendedSteps === true,
170
+ userGlobalWrite: mode === 'global',
170
171
  ...(opts.initialStep !== undefined ? { initialStep: opts.initialStep } : {}),
171
172
  ...(opts.wizardMode !== undefined ? { wizardMode: opts.wizardMode } : {}),
172
173
  }));
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The settings route's handling of the three `git.*` keys.
3
+ *
4
+ * In global mode the route writes the user-global file, and `load_agent_settings`
5
+ * discards `git.*` keys from that file, so a value saved there has no effect in
6
+ * any repository. The form is not offered those keys, and a non-default value is
7
+ * refused with the place a team declares them instead (ADR-283). A template
8
+ * default is accepted: the form round-trips it, and `upgrade` inserts it too.
9
+ *
10
+ * In every mode a value goes through the same check `git:convention show` and
11
+ * `settings:check` run, so a pattern that would reach a shell is refused here as
12
+ * well.
13
+ */
14
+ import { promises as fs } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ import { parseYaml } from './io/yamlIO.js';
17
+ import { GIT_CONVENTION_KEYS, invalidReason } from '../scripts/_lib/git_convention.js';
18
+ export const WITHHELD_GIT_KEYS = GIT_CONVENTION_KEYS.map((k) => `git.${k}`);
19
+ export const WITHHELD_REASON = 'This form writes your user-global settings file, which does not carry git.* keys. ' +
20
+ 'A team declares them in .git-convention.yml at the repository root; one checkout can set them in its project settings file.';
21
+ function _gitSection(values) {
22
+ const git = values['git'];
23
+ return git !== null && typeof git === 'object' && !Array.isArray(git) ? git : null;
24
+ }
25
+ /** The values and the JSON schema with the `git` section removed. */
26
+ export function withholdGitKeys(values, schema) {
27
+ const { git: _git, ...rest } = values;
28
+ const properties = { ...(schema.properties ?? {}) };
29
+ delete properties['git'];
30
+ const next = { ...schema, properties };
31
+ if (Array.isArray(schema.required))
32
+ next.required = schema.required.filter((k) => k !== 'git');
33
+ return { values: rest, schema: next };
34
+ }
35
+ /**
36
+ * Field issues for the `git.*` values of a write. `defaults` is the template's
37
+ * `git` section; `userGlobal` is true when the write lands in the user-global file.
38
+ */
39
+ export function gitKeyWriteIssues(values, defaults, userGlobal) {
40
+ const git = _gitSection(values);
41
+ if (git === null)
42
+ return [];
43
+ const fallback = _gitSection(defaults) ?? {};
44
+ const issues = [];
45
+ for (const key of GIT_CONVENTION_KEYS) {
46
+ const value = git[key];
47
+ if (typeof value !== 'string')
48
+ continue;
49
+ const why = invalidReason(key, value);
50
+ if (why !== null) {
51
+ issues.push({ path: `git.${key}`, message: why });
52
+ continue;
53
+ }
54
+ const def = fallback[key];
55
+ if (userGlobal && !(typeof def === 'string' && def === value)) {
56
+ issues.push({ path: `git.${key}`, message: WITHHELD_REASON });
57
+ }
58
+ }
59
+ return issues;
60
+ }
61
+ /**
62
+ * The write candidate with the `git` section the file already holds. In global
63
+ * mode the form never showed that section, and the schema's `.default({})`
64
+ * fills template defaults into whatever arrives, so a value the user-global
65
+ * file carries would otherwise read as a change the user made: a guarded-key
66
+ * confirmation for a field they never saw, then a silent reset.
67
+ *
68
+ * `fileValues` is that file alone, never the merged view: the merge carries
69
+ * the template defaults and any project layer, and copying a project value
70
+ * here would write it into the user-global file without passing the gate.
71
+ */
72
+ export function keepWithheldGit(candidate, fileValues) {
73
+ const { git: _sent, ...rest } = candidate;
74
+ return 'git' in fileValues ? { ...rest, git: fileValues['git'] } : rest;
75
+ }
76
+ /**
77
+ * The before-side of a global-mode diff: the merged view with its `git` section
78
+ * swapped for the file's own, or dropped when the file has none. The candidate
79
+ * from `keepWithheldGit` carries exactly that section, so comparing it against
80
+ * the merged view would report template defaults and project values as edits
81
+ * to a section the form never showed.
82
+ */
83
+ export function gitDiffBase(merged, fileValues) {
84
+ return keepWithheldGit(merged, fileValues);
85
+ }
86
+ /**
87
+ * The wizard's finish write through the same gate: a 422 is sent and true
88
+ * returned when a `git.*` value is refused. The template's `git` section holds
89
+ * no install placeholder, so it is parsed without substitution.
90
+ */
91
+ export async function refuseGitKeys(reply, values, packageRoot, userGlobal) {
92
+ let defaults = {};
93
+ try {
94
+ defaults = parseYaml(await fs.readFile(join(packageRoot, 'src', 'config', 'agent-settings.template.yml'), 'utf8'));
95
+ }
96
+ catch {
97
+ defaults = {};
98
+ }
99
+ const issues = gitKeyWriteIssues(values, defaults, userGlobal);
100
+ if (issues.length === 0)
101
+ return false;
102
+ await reply.code(422).send({ error: { code: 'VALIDATION', message: 'invalid settings', fields: issues } });
103
+ return true;
104
+ }
105
+ //# sourceMappingURL=gitKeysGate.js.map
@@ -1,12 +1,36 @@
1
1
  import { promises as fs } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
+ import { isDeepStrictEqual } from 'node:util';
3
4
  import { zodToJsonSchema } from 'zod-to-json-schema';
4
5
  import { settingsSchema } from '../schemas/settings.js';
5
- import { parseYaml, mergeIntoTemplate, diffValues, deepMerge, TEMPLATE_PLACEHOLDER_DEFAULTS } from '../io/yamlIO.js';
6
+ import { parseYaml, mergeIntoTemplate, diffValues, deepMerge, renderSparseSettings, substituteTemplatePlaceholders, TEMPLATE_PLACEHOLDER_DEFAULTS } from '../io/yamlIO.js';
7
+ import { sparseSettingsValues } from './wizard.js';
6
8
  import { writeAtomic } from '../io/atomicWrite.js';
9
+ import { WITHHELD_GIT_KEYS, WITHHELD_REASON, gitDiffBase, gitKeyWriteIssues, keepWithheldGit, withholdGitKeys } from '../gitKeysGate.js';
7
10
  import { sharedWriteTarget, resolveThroughSymlinks } from '../io/sharedWriteCheck.js';
8
11
  import { PACKAGE_ROOT } from '../../cli/paths.js';
9
12
  import { buildSettingsClassIndex, guardedChangedKeys, parseSettingsClassRows } from '../../shared/settingsClasses.js';
13
+ /**
14
+ * A fresh user-global file records decisions, not the defaults: the form posts
15
+ * every value, and a copy of the template's would freeze each default at today's
16
+ * value. Only leaves that differ from the template are kept, over the carve-outs.
17
+ */
18
+ async function freshUserGlobalValues(packageRoot, candidate) {
19
+ const templateBody = await fs.readFile(join(packageRoot, 'src', 'config', 'agent-settings.template.yml'), 'utf8');
20
+ const template = parseYaml(substituteTemplatePlaceholders(templateBody));
21
+ const decided = (value, dflt) => {
22
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
23
+ const base = dflt !== null && typeof dflt === 'object' && !Array.isArray(dflt) ? dflt : {};
24
+ const kept = Object.entries(value)
25
+ .map(([k, v]) => [k, decided(v, base[k])])
26
+ .filter(([, v]) => v !== undefined);
27
+ return kept.length === 0 ? undefined : Object.fromEntries(kept);
28
+ }
29
+ return isDeepStrictEqual(value, dflt) ? undefined : value;
30
+ };
31
+ const own = (decided(candidate, template) ?? {});
32
+ return deepMerge(sparseSettingsValues(templateBody, {}), own);
33
+ }
10
34
  /** Sidecar written by `settings:set`, keyed by dotted path. */
11
35
  const PROVENANCE_RELATIVE = join('settings', '.agent-settings.provenance.json');
12
36
  /**
@@ -217,6 +241,8 @@ async function readLayeredSettings(packageRoot, writeRoot, legacyReadRoot, userG
217
241
  ])],
218
242
  project: projectLayer !== null ? dottedLeafPaths(projectLayer.values) : [],
219
243
  },
244
+ writeLayer: globalLayer?.values ?? null,
245
+ writeLayerRaw: globalLayer?.raw ?? null,
220
246
  };
221
247
  }
222
248
  function zodIssuesToFields(issues) {
@@ -234,6 +260,10 @@ export function settingsRoute(opts) {
234
260
  app.get('/api/v1/settings', async (_request, reply) => {
235
261
  try {
236
262
  const state = await readLayeredSettings(packageRoot, opts.writeRoot, opts.legacyReadRoot, opts.userGlobalReadRoot);
263
+ const offered = opts.userGlobalWrite === true
264
+ ? withholdGitKeys(state.values, SETTINGS_JSON_SCHEMA)
265
+ : { values: state.values, schema: SETTINGS_JSON_SCHEMA };
266
+ const withheld = opts.userGlobalWrite === true ? { withheld: { keys: WITHHELD_GIT_KEYS, reason: WITHHELD_REASON } } : {};
237
267
  if (!state.hasRealFile) {
238
268
  // No on-disk file yet — the wizard creates it. Surface the
239
269
  // template-defaults values + schema + path in the body so
@@ -242,19 +272,21 @@ export function settingsRoute(opts) {
242
272
  // `{}` and the user's first save fails schema validation).
243
273
  await reply.code(404).send({
244
274
  error: { code: 'NOT_FOUND', message: 'settings file missing' },
245
- defaults: state.values,
275
+ defaults: offered.values,
246
276
  lastModified: 0,
247
277
  path: SETTINGS_RELATIVE,
248
- schema: SETTINGS_JSON_SCHEMA,
278
+ schema: offered.schema,
279
+ ...withheld,
249
280
  });
250
281
  return reply;
251
282
  }
252
283
  const legacyHints = extractLegacyHints(state.values);
253
284
  return {
254
- values: state.values,
285
+ values: offered.values,
255
286
  lastModified: state.mtimeMs,
256
287
  path: SETTINGS_RELATIVE,
257
- schema: SETTINGS_JSON_SCHEMA,
288
+ schema: offered.schema,
289
+ ...withheld,
258
290
  legacyHints,
259
291
  // Phase 5.4 — per-layer provenance for the settings hub's
260
292
  // "set globally / in this project" source badges.
@@ -293,7 +325,13 @@ export function settingsRoute(opts) {
293
325
  });
294
326
  return reply;
295
327
  }
296
- const changes = diffValues(current.values, parsed.data);
328
+ const candidate = opts.userGlobalWrite === true
329
+ ? keepWithheldGit(parsed.data, current.writeLayer ?? {})
330
+ : parsed.data;
331
+ const before = opts.userGlobalWrite === true
332
+ ? gitDiffBase(current.values, current.writeLayer ?? {})
333
+ : current.values;
334
+ const changes = diffValues(before, candidate);
297
335
  return { changes };
298
336
  });
299
337
  app.put('/api/v1/settings', async (request, reply) => {
@@ -310,6 +348,11 @@ export function settingsRoute(opts) {
310
348
  });
311
349
  return reply;
312
350
  }
351
+ const gitIssues = gitKeyWriteIssues(parsed.data, await loadDefaultSettings(packageRoot), opts.userGlobalWrite === true);
352
+ if (gitIssues.length > 0) {
353
+ await reply.code(422).send({ error: { code: 'VALIDATION', message: 'invalid settings', fields: gitIssues } });
354
+ return reply;
355
+ }
313
356
  const current = await readLayeredSettings(packageRoot, opts.writeRoot, opts.legacyReadRoot, opts.userGlobalReadRoot);
314
357
  if (!current.hasRealFile) {
315
358
  await reply.code(404).send({ error: { code: 'NOT_FOUND', message: 'settings file missing' } });
@@ -322,8 +365,22 @@ export function settingsRoute(opts) {
322
365
  });
323
366
  return reply;
324
367
  }
368
+ const candidate = opts.userGlobalWrite === true
369
+ ? keepWithheldGit(parsed.data, current.writeLayer ?? {})
370
+ : parsed.data;
325
371
  try {
326
- const merged = mergeIntoTemplate(current.raw, parsed.data);
372
+ // In global mode the scaffold may be the project file, whose
373
+ // git section the candidate does not overwrite; the file being
374
+ // written is the base, so a section it lacks stays absent. An
375
+ // absent user-global file is rendered the way the wizard renders
376
+ // a fresh one: merging into an empty body appends flat dotted
377
+ // keys, which no reader resolves.
378
+ const ownRaw = current.writeLayerRaw;
379
+ const merged = opts.userGlobalWrite !== true
380
+ ? mergeIntoTemplate(current.raw, candidate)
381
+ : ownRaw !== null
382
+ ? mergeIntoTemplate(ownRaw, candidate)
383
+ : renderSparseSettings(await freshUserGlobalValues(packageRoot, candidate));
327
384
  if (opts.dryRun === true) {
328
385
  // No disk write, no Last-Modified bump — surface the
329
386
  // rendered body so the maintainer sees what a real
@@ -352,7 +409,9 @@ export function settingsRoute(opts) {
352
409
  // this point and is not gated — it writes nothing.
353
410
  if (body.confirmGuarded !== true) {
354
411
  const classes = await readClassIndex(packageRoot);
355
- const guarded = guardedChangedKeys(classes, diffValues(current.values, parsed.data));
412
+ const guarded = guardedChangedKeys(classes, diffValues(opts.userGlobalWrite === true
413
+ ? gitDiffBase(current.values, current.writeLayer ?? {})
414
+ : current.values, candidate));
356
415
  if (guarded.length > 0) {
357
416
  await reply.code(409).send({
358
417
  error: 'guarded-keys',
@@ -19,6 +19,7 @@ import { detectAgentSwitch, AGENT_SWITCH_INSTALL_COMMAND, AGENT_SWITCH_REPO } fr
19
19
  import { readDismissedRecommendations, dismissRecommendation } from '../../install/wizardDismissals.js';
20
20
  import { installCompleted, installDoneSummary } from '../../install/preserve.js';
21
21
  import { apiOnQuotaView } from '../../scripts/ai_council/transport_resolver.js';
22
+ import { refuseGitKeys } from '../gitKeysGate.js';
22
23
  const STATE_REL = join('state', 'wizard-state.json');
23
24
  const SETTINGS_REL = join('settings', '.agent-settings.yml');
24
25
  const USER_IDENTITY_REL = join('settings', '.agent-user.yml');
@@ -1198,6 +1199,9 @@ export function wizardRoute(opts) {
1198
1199
  const effectiveWriteRoot = scope === 'project' && projectScopeRoot !== null
1199
1200
  ? projectScopeRoot
1200
1201
  : opts.writeRoot;
1202
+ const userGlobalTarget = opts.userGlobalWrite === true && effectiveWriteRoot === opts.writeRoot;
1203
+ if (await refuseGitKeys(reply, settingsParsed.data, opts.packageRoot, userGlobalTarget))
1204
+ return reply;
1201
1205
  try {
1202
1206
  const template = await readTemplate(opts.packageRoot);
1203
1207
  const answers = settingsParsed.data;