@event4u/agent-config 16.2.0 → 16.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (651) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +337 -234
  5. package/README.md +15 -13
  6. package/agents/templates/.ai-council.yml.example +26 -8
  7. package/dist/agent-src/commands/analyze/inbox.md +11 -8
  8. package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
  9. package/dist/agent-src/commands/bug/fix.md +17 -2
  10. package/dist/agent-src/commands/bug/investigate.md +1 -1
  11. package/dist/agent-src/commands/commit/in-chunks.md +40 -31
  12. package/dist/agent-src/commands/commit.md +72 -33
  13. package/dist/agent-src/commands/condense.md +2 -8
  14. package/dist/agent-src/commands/council/debate.md +11 -7
  15. package/dist/agent-src/commands/council/default.md +10 -9
  16. package/dist/agent-src/commands/council.md +1 -1
  17. package/dist/agent-src/commands/estimate-ticket.md +1 -1
  18. package/dist/agent-src/commands/feature/explore.md +3 -3
  19. package/dist/agent-src/commands/feature/plan.md +2 -2
  20. package/dist/agent-src/commands/feature/roadmap.md +1 -1
  21. package/dist/agent-src/commands/fix/ci.md +18 -4
  22. package/dist/agent-src/commands/fix/commit-messages.md +48 -23
  23. package/dist/agent-src/commands/fix/pr-comments.md +3 -6
  24. package/dist/agent-src/commands/implement-ticket.md +4 -4
  25. package/dist/agent-src/commands/jira-ticket.md +1 -1
  26. package/dist/agent-src/commands/memory/add.md +4 -16
  27. package/dist/agent-src/commands/memory/load.md +5 -6
  28. package/dist/agent-src/commands/memory/promote.md +3 -16
  29. package/dist/agent-src/commands/mission/upgrade.md +3 -2
  30. package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
  31. package/dist/agent-src/commands/optimize/deep.md +4 -2
  32. package/dist/agent-src/commands/optimize/rtk.md +4 -26
  33. package/dist/agent-src/commands/pr/create/description-only.md +18 -15
  34. package/dist/agent-src/commands/pr/create.md +42 -34
  35. package/dist/agent-src/commands/pr/merge.md +136 -9
  36. package/dist/agent-src/commands/prepare-for-review.md +13 -11
  37. package/dist/agent-src/commands/project/analyze.md +7 -35
  38. package/dist/agent-src/commands/refine-ticket.md +1 -1
  39. package/dist/agent-src/commands/review/changes.md +14 -19
  40. package/dist/agent-src/commands/roadmap/create.md +1 -1
  41. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  42. package/dist/agent-src/commands/roadmap/next.md +10 -1
  43. package/dist/agent-src/commands/roadmap/process-full.md +56 -42
  44. package/dist/agent-src/commands/roadmap/resolve-blockers.md +411 -0
  45. package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
  46. package/dist/agent-src/commands/roadmap.md +18 -4
  47. package/dist/agent-src/commands/tests/create.md +17 -3
  48. package/dist/agent-src/commands/tests/execute.md +22 -5
  49. package/dist/agent-src/commands/worktree/create.md +7 -3
  50. package/dist/agent-src/commands/worktree/verify.md +2 -1
  51. package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
  52. package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
  53. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
  54. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
  55. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
  56. package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
  57. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +7 -7
  58. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
  59. package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
  60. package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
  61. package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
  62. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
  63. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +99 -54
  64. package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
  65. package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
  66. package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
  67. package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
  68. package/dist/agent-src/contexts/execution/toolchain-resolver.md +95 -7
  69. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  70. package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  71. package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  72. package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  73. package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  74. package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
  75. package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  76. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  77. package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
  78. package/dist/agent-src/guidelines/php/git.md +15 -2
  79. package/dist/agent-src/rules/active-remediation.md +1 -2
  80. package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
  81. package/dist/agent-src/rules/architecture.md +0 -1
  82. package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
  83. package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
  84. package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
  85. package/dist/agent-src/rules/autonomous-execution.md +1 -1
  86. package/dist/agent-src/rules/brand-consistency.md +0 -1
  87. package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
  88. package/dist/agent-src/rules/broken-access-control.md +1 -1
  89. package/dist/agent-src/rules/cli-output-handling.md +0 -1
  90. package/dist/agent-src/rules/code-comment-discipline.md +0 -1
  91. package/dist/agent-src/rules/code-provenance.md +0 -1
  92. package/dist/agent-src/rules/command-suggestion-policy.md +1 -1
  93. package/dist/agent-src/rules/commit-conventions.md +1 -2
  94. package/dist/agent-src/rules/communication-through-line.md +1 -2
  95. package/dist/agent-src/rules/content-quoting-floor.md +1 -2
  96. package/dist/agent-src/rules/context-hygiene.md +6 -6
  97. package/dist/agent-src/rules/copilot-routing.md +1 -2
  98. package/dist/agent-src/rules/council-availability.md +4 -4
  99. package/dist/agent-src/rules/cross-source-consistency.md +4 -6
  100. package/dist/agent-src/rules/decision-revisit-gate.md +17 -35
  101. package/dist/agent-src/rules/delegation-policy.md +2 -3
  102. package/dist/agent-src/rules/design-fidelity.md +12 -16
  103. package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
  104. package/dist/agent-src/rules/devcontainer-routing.md +1 -2
  105. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
  106. package/dist/agent-src/rules/docker-commands.md +0 -1
  107. package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
  108. package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -1
  109. package/dist/agent-src/rules/domain-safety-pii.md +1 -1
  110. package/dist/agent-src/rules/domain-safety-retention.md +1 -1
  111. package/dist/agent-src/rules/downstream-changes.md +0 -1
  112. package/dist/agent-src/rules/engineering-safety-floor.md +1 -1
  113. package/dist/agent-src/rules/evaluator-independence.md +3 -2
  114. package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
  115. package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
  116. package/dist/agent-src/rules/fast-path-marker-visibility.md +2 -2
  117. package/dist/agent-src/rules/finance-safety-floor.md +1 -1
  118. package/dist/agent-src/rules/fix-what-you-see.md +6 -32
  119. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
  120. package/dist/agent-src/rules/git-history-discipline.md +2 -2
  121. package/dist/agent-src/rules/guidelines.md +0 -1
  122. package/dist/agent-src/rules/history-discipline.md +0 -1
  123. package/dist/agent-src/rules/icon-consistency.md +0 -1
  124. package/dist/agent-src/rules/image-likeness-and-rights.md +1 -1
  125. package/dist/agent-src/rules/improve-before-implement.md +0 -1
  126. package/dist/agent-src/rules/invite-challenge.md +0 -1
  127. package/dist/agent-src/rules/laravel-routing.md +1 -2
  128. package/dist/agent-src/rules/laravel-translations.md +0 -1
  129. package/dist/agent-src/rules/legal-safety-floor.md +3 -3
  130. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -1
  131. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
  132. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -1
  133. package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
  134. package/dist/agent-src/rules/media-governance-routing.md +13 -17
  135. package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
  136. package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
  137. package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
  138. package/dist/agent-src/rules/missing-tool-handling.md +0 -1
  139. package/dist/agent-src/rules/model-recommendation.md +0 -1
  140. package/dist/agent-src/rules/neighbour-precedence.md +64 -0
  141. package/dist/agent-src/rules/no-attribution-footers.md +0 -1
  142. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
  143. package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
  144. package/dist/agent-src/rules/no-roadmap-references.md +0 -1
  145. package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
  146. package/dist/agent-src/rules/onboarding-gate.md +0 -1
  147. package/dist/agent-src/rules/output-discipline.md +0 -1
  148. package/dist/agent-src/rules/package-ci-checks.md +0 -1
  149. package/dist/agent-src/rules/persona-governance.md +4 -5
  150. package/dist/agent-src/rules/php-coding.md +0 -1
  151. package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
  152. package/dist/agent-src/rules/preservation-guard.md +0 -1
  153. package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -4
  154. package/dist/agent-src/rules/question-not-instruction.md +1 -1
  155. package/dist/agent-src/rules/reviewer-awareness.md +0 -1
  156. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
  157. package/dist/agent-src/rules/roadmap-progress-sync.md +4 -7
  158. package/dist/agent-src/rules/role-mode-adherence.md +0 -1
  159. package/dist/agent-src/rules/rule-type-governance.md +0 -1
  160. package/dist/agent-src/rules/runtime-safety.md +1 -1
  161. package/dist/agent-src/rules/scale-discipline.md +0 -1
  162. package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
  163. package/dist/agent-src/rules/security-sensitive-stop.md +3 -3
  164. package/dist/agent-src/rules/self-repair-loop.md +0 -1
  165. package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
  166. package/dist/agent-src/rules/session-canary.md +7 -62
  167. package/dist/agent-src/rules/settings-ask-protocol.md +6 -6
  168. package/dist/agent-src/rules/size-enforcement.md +0 -1
  169. package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
  170. package/dist/agent-src/rules/skill-quality.md +0 -1
  171. package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
  172. package/dist/agent-src/rules/source-confidentiality.md +1 -1
  173. package/dist/agent-src/rules/source-discovery-gate.md +0 -1
  174. package/dist/agent-src/rules/source-of-truth.md +0 -1
  175. package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
  176. package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
  177. package/dist/agent-src/rules/symfony-routing.md +1 -2
  178. package/dist/agent-src/rules/think-before-action.md +0 -1
  179. package/dist/agent-src/rules/token-budget-discipline.md +12 -46
  180. package/dist/agent-src/rules/token-efficiency.md +0 -1
  181. package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
  182. package/dist/agent-src/rules/tool-safety.md +1 -1
  183. package/dist/agent-src/rules/ui-audit-gate.md +1 -2
  184. package/dist/agent-src/rules/untrusted-input-defense.md +1 -1
  185. package/dist/agent-src/rules/upstream-proposal.md +0 -1
  186. package/dist/agent-src/rules/user-interaction.md +0 -1
  187. package/dist/agent-src/rules/user-interrupt-priority.md +1 -1
  188. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  189. package/dist/agent-src/scripts/deferral_carry.ts +339 -0
  190. package/dist/agent-src/scripts/gate_budget.ts +47 -23
  191. package/dist/agent-src/scripts/gate_execute.ts +12 -4
  192. package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
  193. package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
  194. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
  195. package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
  196. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
  197. package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
  198. package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
  199. package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
  200. package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
  201. package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
  202. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
  203. package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
  204. package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
  205. package/dist/agent-src/skills/database/data/manifest.json +2 -2
  206. package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
  207. package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
  208. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
  209. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  210. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +2 -2
  211. package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
  212. package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
  213. package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
  214. package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
  215. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
  216. package/dist/agent-src/skills/iconography/SKILL.md +1 -1
  217. package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
  218. package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
  219. package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
  220. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
  221. package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
  222. package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
  223. package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
  224. package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
  225. package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
  226. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  227. package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
  228. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
  229. package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
  230. package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
  231. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +4 -2
  232. package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
  233. package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
  234. package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
  235. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  236. package/dist/agent-src/skills/ui-component-architect/SKILL.md +2 -2
  237. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  238. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
  239. package/dist/agent-src/templates/AGENTS.md +1 -1
  240. package/dist/agent-src/templates/agent-settings.md +46 -129
  241. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
  242. package/dist/agent-src/templates/command.md +2 -2
  243. package/dist/agent-src/templates/roadmaps.md +6 -1
  244. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  245. package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  246. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  247. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  248. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  249. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  250. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  251. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  252. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  253. package/dist/agent-src/templates/skill.md +1 -1
  254. package/dist/cli/registry.js +2 -1
  255. package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
  256. package/dist/cli-delegate/check_update_banner.js +207 -120
  257. package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
  258. package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-5GPULQBE.js} +2797 -338
  259. package/dist/cli-delegate/{chunk-IGD6ERX6.js → chunk-6SRJTYJS.js} +42 -176
  260. package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
  261. package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
  262. package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
  263. package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
  264. package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
  265. package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-AED2VQGM.js} +1245 -249
  266. package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
  267. package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
  268. package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
  269. package/dist/cli-delegate/chunk-F3QDG2GT.js +2569 -0
  270. package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-G5VVIZRC.js} +3 -3
  271. package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-H76PHZBI.js} +149 -61
  272. package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
  273. package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
  274. package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
  275. package/dist/cli-delegate/{chunk-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
  276. package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-KXXWJTDO.js} +6 -11
  277. package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
  278. package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-MDPPKQCQ.js} +58 -9
  279. package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-MSUL5NYP.js} +5 -5
  280. package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
  281. package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
  282. package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
  283. package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-PWX7CKMD.js} +4 -4
  284. package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
  285. package/dist/cli-delegate/{chunk-7XGBX6ZH.js → chunk-T7XSJSUQ.js} +1144 -589
  286. package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
  287. package/dist/cli-delegate/chunk-WQWXGIWB.js +1779 -0
  288. package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-XQTPXKFA.js} +1 -1
  289. package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
  290. package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
  291. package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
  292. package/dist/cli-delegate/cmd_analyze_session.js +223 -43
  293. package/dist/cli-delegate/cmd_brand_status.js +3 -2
  294. package/dist/cli-delegate/cmd_conformance.js +1252 -249
  295. package/dist/cli-delegate/cmd_converge.js +3 -3
  296. package/dist/cli-delegate/cmd_doctor.js +19 -9
  297. package/dist/cli-delegate/cmd_doctor_neighbours.js +30 -0
  298. package/dist/cli-delegate/cmd_explain.js +45 -21
  299. package/dist/cli-delegate/cmd_export.js +13 -10
  300. package/dist/cli-delegate/cmd_fleet.js +3 -3
  301. package/dist/cli-delegate/cmd_git_convention.js +1851 -0
  302. package/dist/cli-delegate/cmd_handoff.js +44 -22
  303. package/dist/cli-delegate/cmd_mcp_available.js +3 -2
  304. package/dist/cli-delegate/cmd_memory_get.js +3 -1
  305. package/dist/cli-delegate/cmd_migrate.js +3 -3
  306. package/dist/cli-delegate/cmd_packs_active.js +5 -4
  307. package/dist/cli-delegate/cmd_preflight.js +6 -6
  308. package/dist/cli-delegate/cmd_prune.js +14 -11
  309. package/dist/cli-delegate/cmd_refresh.js +2 -1
  310. package/dist/cli-delegate/cmd_route_audit.js +10 -8
  311. package/dist/cli-delegate/cmd_route_explain.js +4 -4
  312. package/dist/cli-delegate/cmd_session_recycle.js +10 -7
  313. package/dist/cli-delegate/cmd_settings_check.js +54 -7
  314. package/dist/cli-delegate/cmd_settings_get.js +18 -8
  315. package/dist/cli-delegate/cmd_settings_migrate.js +13 -10
  316. package/dist/cli-delegate/cmd_settings_set.js +4 -4
  317. package/dist/cli-delegate/cmd_sync.js +14 -11
  318. package/dist/cli-delegate/cmd_uninstall.js +15 -12
  319. package/dist/cli-delegate/cmd_update.js +7 -7
  320. package/dist/cli-delegate/cmd_upgrade.js +9 -8
  321. package/dist/cli-delegate/cmd_validate.js +15 -12
  322. package/dist/cli-delegate/cmd_versions.js +5 -5
  323. package/dist/cli-delegate/deferral_carry.js +16 -0
  324. package/dist/cli-delegate/gate_budget.js +1 -1
  325. package/dist/cli-delegate/gate_execute.js +3 -3
  326. package/dist/cli-delegate/roadmap_gates.js +6 -6
  327. package/dist/cli-delegate/update_roadmap_progress.js +1 -1
  328. package/dist/discovery/deprecation-report.md +1 -1
  329. package/dist/discovery/discovery-manifest.json +232 -141
  330. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  331. package/dist/discovery/discovery-manifest.summary.md +3 -3
  332. package/dist/discovery/dormancy-report.md +1 -1
  333. package/dist/discovery/orphan-report.md +1 -1
  334. package/dist/discovery/packs.json +26 -9
  335. package/dist/discovery/trust-report.md +3 -3
  336. package/dist/discovery/workspaces.json +7 -4
  337. package/dist/hooks/dispatch.js +5655 -6623
  338. package/dist/hooks/dispatch.sha256 +1 -1
  339. package/dist/install/claudePathsPlan.js +47 -6
  340. package/dist/install/claudeRuleRewrite.js +7 -0
  341. package/dist/install/emit_host_rules_cli.js +39 -36
  342. package/dist/install/globalRuleScope.js +87 -0
  343. package/dist/install/host_rule_ownership.js +160 -0
  344. package/dist/install/install.mjs +2336 -1249
  345. package/dist/install/installThinLayer.js +289 -0
  346. package/dist/install/installedRuleLinks.js +262 -0
  347. package/dist/install/wizard-plan.js +24 -0
  348. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  349. package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
  350. package/dist/mcp/registry-manifest.json +5 -5
  351. package/dist/mcp/server.json +2 -2
  352. package/dist/mcp/server.mjs +36504 -30986
  353. package/dist/router.json +1 -1
  354. package/dist/scripts/_lib/agent_settings.js +26 -120
  355. package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
  356. package/dist/scripts/_lib/compile_time_toggles.js +12 -21
  357. package/dist/scripts/_lib/git_convention.js +232 -0
  358. package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
  359. package/dist/scripts/_lib/installed_layer.js +704 -0
  360. package/dist/scripts/_lib/lean_projection_mode.js +218 -15
  361. package/dist/scripts/_lib/package_root.js +68 -0
  362. package/dist/scripts/_lib/rule_consequence_class.js +45 -0
  363. package/dist/scripts/_lib/rule_injection.js +67 -10
  364. package/dist/scripts/_lib/rule_law_section.js +122 -0
  365. package/dist/scripts/_lib/settings_removed_keys.js +168 -0
  366. package/dist/scripts/_lib/thin_rules.js +535 -0
  367. package/dist/scripts/_lib/windsurf_render.js +60 -0
  368. package/dist/scripts/condense.js +14 -26
  369. package/dist/scripts/project_thin_rules.js +14 -294
  370. package/dist/server/app.js +2 -1
  371. package/dist/server/gitKeysGate.js +105 -0
  372. package/dist/server/routes/settings.js +67 -8
  373. package/dist/server/routes/wizard.js +4 -0
  374. package/dist/server/schemas/settings.js +29 -81
  375. package/dist/shared/skillRanking.js +103 -16
  376. package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
  377. package/dist/ui/index.html +1 -1
  378. package/docs/MIGRATION.md +72 -1
  379. package/docs/contracts/settings-classes.md +39 -67
  380. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
  381. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
  382. package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
  383. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
  384. package/docs/guidelines/agent-infra/layered-settings.md +13 -1
  385. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
  386. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
  387. package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
  388. package/docs/guidelines/php/git.md +15 -2
  389. package/package.json +1 -1
  390. package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
  391. package/src/agent-src/scripts/deferral_carry.ts +339 -0
  392. package/src/agent-src/scripts/gate_budget.ts +47 -23
  393. package/src/agent-src/scripts/gate_execute.ts +12 -4
  394. package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
  395. package/src/agent-src/templates/AGENTS.md +1 -1
  396. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
  397. package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
  398. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
  399. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
  400. package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
  401. package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
  402. package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
  403. package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
  404. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
  405. package/src/config/agent-settings.template.yml +141 -334
  406. package/src/config/agents-paths.yml +16 -0
  407. package/src/config/assurance-capability-registry.json +7 -3
  408. package/src/config/ci-local-parity.yml +3 -0
  409. package/src/config/continuity-surface.json +10 -3
  410. package/src/config/discovery/packs.yml +17 -1
  411. package/src/config/evaluator-budgets.json +23 -10
  412. package/src/config/gate-coverage.yml +138 -3
  413. package/src/config/gate-violation-baselines.json +64 -16
  414. package/src/config/gitignore-block.txt +19 -0
  415. package/src/config/hook-bundle-budget.json +25 -0
  416. package/src/config/hook-token-budget.json +6 -1
  417. package/src/config/host-instruction-limits.json +33 -0
  418. package/src/config/release-gate-locality.yml +2 -1
  419. package/src/config/routing-coverage-seed.json +67 -4
  420. package/src/config/rule-activation-census.json +7 -3
  421. package/src/config/rule-consequence-class.json +161 -0
  422. package/src/config/rule-law-ceilings.json +105 -0
  423. package/src/config/rule-obligations.json +833 -0
  424. package/src/install/claudePathsPlan.ts +46 -4
  425. package/src/install/claudeRuleRewrite.ts +10 -1
  426. package/src/install/emit_host_rules_cli.ts +43 -34
  427. package/src/install/globalRuleScope.ts +109 -0
  428. package/src/install/host_rule_ownership.ts +170 -0
  429. package/src/install/installThinLayer.ts +378 -0
  430. package/src/install/installedRuleLinks.ts +308 -0
  431. package/src/install/wizard-plan.ts +24 -0
  432. package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
  433. package/src/scripts/_cli/cmd_conformance.ts +13 -2
  434. package/src/scripts/_cli/cmd_doctor.ts +33 -81
  435. package/src/scripts/_cli/cmd_doctor_neighbours.ts +426 -0
  436. package/src/scripts/_cli/cmd_explain.ts +72 -14
  437. package/src/scripts/_cli/cmd_git_convention.ts +637 -0
  438. package/src/scripts/_cli/cmd_settings_check.ts +66 -8
  439. package/src/scripts/_cli/cmd_settings_get.ts +18 -3
  440. package/src/scripts/_cli/doctor_execution.ts +72 -1
  441. package/src/scripts/_dispatch.bash +53 -4
  442. package/src/scripts/_lib/agent_settings.ts +26 -124
  443. package/src/scripts/_lib/blocked_by_marker.ts +1 -1
  444. package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
  445. package/src/scripts/_lib/compile_time_toggles.ts +12 -21
  446. package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
  447. package/src/scripts/_lib/estate_offsets.ts +241 -0
  448. package/src/scripts/_lib/exemption_shape.ts +143 -0
  449. package/src/scripts/_lib/fnv.ts +23 -0
  450. package/src/scripts/_lib/foreign_scan.ts +106 -0
  451. package/src/scripts/_lib/git_base_ref.ts +92 -0
  452. package/src/scripts/_lib/git_convention.ts +291 -0
  453. package/src/scripts/_lib/git_convention_carrier.ts +389 -0
  454. package/src/scripts/_lib/git_convention_grammar.ts +246 -0
  455. package/src/scripts/_lib/git_convention_measure.ts +344 -0
  456. package/src/scripts/_lib/gitignore_block.ts +314 -0
  457. package/src/scripts/_lib/global_deploy_inventory.ts +106 -0
  458. package/src/scripts/_lib/graph_feeder_record.ts +437 -0
  459. package/src/scripts/_lib/hook_settings.ts +73 -0
  460. package/src/scripts/_lib/host_capability.ts +40 -19
  461. package/src/scripts/_lib/host_hook_merge.ts +165 -0
  462. package/src/scripts/_lib/installed_layer.ts +963 -0
  463. package/src/scripts/_lib/json_merge.ts +82 -0
  464. package/src/scripts/_lib/json_pointers.ts +93 -11
  465. package/src/scripts/_lib/knowledge_global.ts +14 -1
  466. package/src/scripts/_lib/lean_projection_mode.ts +275 -15
  467. package/src/scripts/_lib/machine_wake.ts +16 -3
  468. package/src/scripts/_lib/module_reach.ts +456 -0
  469. package/src/scripts/_lib/neighbour_census.ts +760 -0
  470. package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
  471. package/src/scripts/_lib/neighbour_scan.ts +122 -0
  472. package/src/scripts/_lib/neighbour_tool_use.ts +187 -0
  473. package/src/scripts/_lib/prompt_shape.ts +46 -0
  474. package/src/scripts/_lib/ratification_artifact.ts +220 -1
  475. package/src/scripts/_lib/ratification_subject.ts +92 -0
  476. package/src/scripts/_lib/release_findings_ingest.ts +15 -7
  477. package/src/scripts/_lib/release_highlights.ts +5 -0
  478. package/src/scripts/_lib/release_migration_gate.ts +19 -3
  479. package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
  480. package/src/scripts/_lib/review_coverage.ts +134 -0
  481. package/src/scripts/_lib/rule_consequence_class.ts +71 -0
  482. package/src/scripts/_lib/rule_injection.ts +130 -10
  483. package/src/scripts/_lib/rule_law_section.ts +147 -0
  484. package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
  485. package/src/scripts/_lib/rule_obligations.ts +205 -0
  486. package/src/scripts/_lib/self_repair.ts +1 -1
  487. package/src/scripts/_lib/settings_removed_keys.ts +173 -0
  488. package/src/scripts/_lib/skill_origin.ts +254 -0
  489. package/src/scripts/_lib/structured_ask.ts +64 -21
  490. package/src/scripts/_lib/test_red_state.ts +5 -0
  491. package/src/scripts/_lib/thin_rules.ts +620 -0
  492. package/src/scripts/_lib/touched_file_quality.ts +570 -0
  493. package/src/scripts/_lib/turn_end_refusals.ts +77 -2
  494. package/src/scripts/_lib/windsurf_render.ts +63 -0
  495. package/src/scripts/_lib/worker_budget.ts +1 -1
  496. package/src/scripts/adr/regenerate_index.ts +16 -1
  497. package/src/scripts/ai_council/cli_call_budget.ts +13 -5
  498. package/src/scripts/ai_council/clients.ts +26 -57
  499. package/src/scripts/ai_council/config.ts +8 -8
  500. package/src/scripts/ai_council/modification_review.ts +100 -0
  501. package/src/scripts/ai_council/modification_review_questions.ts +90 -0
  502. package/src/scripts/ai_council/orchestrator.ts +5 -5
  503. package/src/scripts/ai_council/spend_gate.ts +18 -7
  504. package/src/scripts/ai_council/vendor_defaults.ts +45 -0
  505. package/src/scripts/ai_team/config.ts +11 -16
  506. package/src/scripts/audit_skill_overlap.ts +261 -0
  507. package/src/scripts/audit_user_type_axis.ts +20 -8
  508. package/src/scripts/before_complete_hook.ts +243 -12
  509. package/src/scripts/bench_ab_clone.ts +1 -2
  510. package/src/scripts/bench_concern_spawn_path.ts +129 -0
  511. package/src/scripts/bench_graph_feeder_latency.ts +584 -0
  512. package/src/scripts/bench_touched_file_quality.ts +238 -0
  513. package/src/scripts/check_agent_artifact_location.ts +36 -0
  514. package/src/scripts/check_branch_freshness.ts +147 -24
  515. package/src/scripts/check_enforcement_coverage.ts +130 -0
  516. package/src/scripts/check_enforcement_matrix.ts +377 -20
  517. package/src/scripts/check_estate_count.ts +130 -153
  518. package/src/scripts/check_evaluator_budgets.ts +4 -0
  519. package/src/scripts/check_finding_dispositions.ts +196 -21
  520. package/src/scripts/check_gate_coverage.ts +4 -3
  521. package/src/scripts/check_gate_reachability.ts +48 -1
  522. package/src/scripts/check_generator_sync.ts +48 -0
  523. package/src/scripts/check_hook_bundle_composition.ts +477 -0
  524. package/src/scripts/check_kernel_edit_ratified.ts +132 -14
  525. package/src/scripts/check_memory.ts +7 -1
  526. package/src/scripts/check_pack_size.ts +1 -1
  527. package/src/scripts/check_release_highlights.ts +10 -0
  528. package/src/scripts/check_release_manifest_content.ts +189 -0
  529. package/src/scripts/check_release_pr_shape.ts +38 -15
  530. package/src/scripts/check_standing_rule_delivery.ts +129 -13
  531. package/src/scripts/check_suppression_hygiene.ts +2 -5
  532. package/src/scripts/check_verify_expectation_delta.ts +521 -0
  533. package/src/scripts/ci_settle.ts +42 -5
  534. package/src/scripts/classify_merge_risk.ts +320 -0
  535. package/src/scripts/closure_scan.ts +91 -1
  536. package/src/scripts/code_graph/detect.ts +127 -7
  537. package/src/scripts/code_graph/foreign.ts +194 -0
  538. package/src/scripts/code_graph/query.ts +217 -4
  539. package/src/scripts/code_graph/types.ts +26 -2
  540. package/src/scripts/code_graph/validate.ts +3 -1
  541. package/src/scripts/code_graph/verbs.ts +103 -0
  542. package/src/scripts/command_suggester/settings.ts +8 -108
  543. package/src/scripts/command_suggester/types.ts +4 -5
  544. package/src/scripts/compile_hook_manifest.ts +33 -1
  545. package/src/scripts/condense.ts +14 -27
  546. package/src/scripts/consumer_matrix.ts +102 -0
  547. package/src/scripts/context_hygiene_hook.ts +13 -23
  548. package/src/scripts/cost/preflight.mjs +12 -1
  549. package/src/scripts/council_cli.ts +7 -7
  550. package/src/scripts/dispatch_r2_reviewer.ts +24 -11
  551. package/src/scripts/estate_exemption_shape.ts +202 -0
  552. package/src/scripts/explain_run.ts +8 -13
  553. package/src/scripts/generate_git_convention_grammar.ts +127 -0
  554. package/src/scripts/generate_host_cost_table.ts +21 -4
  555. package/src/scripts/handoff_context_hook.ts +86 -37
  556. package/src/scripts/hook_manifest.json +1 -1
  557. package/src/scripts/hook_manifest.yaml +175 -15
  558. package/src/scripts/hooks/block_config_weakening.ts +115 -7
  559. package/src/scripts/hooks/block_plumbing_writes.ts +37 -5
  560. package/src/scripts/hooks/code_graph_context_hook.ts +252 -23
  561. package/src/scripts/hooks/concern_failure_policy.ts +280 -0
  562. package/src/scripts/hooks/concern_registry.ts +2 -0
  563. package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
  564. package/src/scripts/hooks/dispatch_hook.ts +52 -52
  565. package/src/scripts/hooks/evidence_independence.ts +12 -4
  566. package/src/scripts/hooks/exit_codes.ts +2 -1
  567. package/src/scripts/hooks/host_lowering.json +1 -1
  568. package/src/scripts/hooks/host_lowering.ts +19 -1
  569. package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
  570. package/src/scripts/hooks/one_question_per_ask_hook.ts +41 -25
  571. package/src/scripts/hooks/payload_stub.ts +10 -1
  572. package/src/scripts/hooks/push_settle_hook.ts +4 -3
  573. package/src/scripts/hooks/rule_inject_hook.ts +795 -60
  574. package/src/scripts/hooks/state_io.ts +8 -4
  575. package/src/scripts/hooks/table_fingerprint.ts +21 -0
  576. package/src/scripts/hooks/telemetry_usage_hook.ts +24 -7
  577. package/src/scripts/hooks/turn_end_gate_hook.ts +85 -0
  578. package/src/scripts/hooks_status.ts +112 -0
  579. package/src/scripts/injection_scan_hook.ts +7 -0
  580. package/src/scripts/install-hooks.sh +42 -14
  581. package/src/scripts/install.ts +78 -215
  582. package/src/scripts/installed_layer_report.ts +103 -0
  583. package/src/scripts/language_mirror_hook.ts +15 -6
  584. package/src/scripts/learning_sidecar.ts +119 -8
  585. package/src/scripts/lint_blocker_citations.ts +198 -0
  586. package/src/scripts/lint_evidence_artifacts.ts +9 -0
  587. package/src/scripts/lint_hook_concern_budget.ts +10 -21
  588. package/src/scripts/lint_hook_manifest.ts +53 -0
  589. package/src/scripts/lint_major_migration_sections.ts +156 -26
  590. package/src/scripts/lint_pack_boundaries.ts +465 -29
  591. package/src/scripts/lint_roadmap_blockers.ts +282 -29
  592. package/src/scripts/lint_roadmap_complexity.ts +4 -2
  593. package/src/scripts/lint_rule_law_section.ts +647 -0
  594. package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
  595. package/src/scripts/lint_settings_classes.ts +1 -1
  596. package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
  597. package/src/scripts/lint_workflow_security.ts +173 -6
  598. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
  599. package/src/scripts/mcp_server/graph_tools.ts +72 -3
  600. package/src/scripts/measure_routing_signal.ts +54 -16
  601. package/src/scripts/measure_skill_ranker_baseline.ts +221 -8
  602. package/src/scripts/memory_learn_hook.ts +91 -6
  603. package/src/scripts/model_rule_injection.ts +55 -8
  604. package/src/scripts/onboarding_gate_hook.ts +7 -6
  605. package/src/scripts/print_required_checks.ts +15 -3
  606. package/src/scripts/probe_host_compliance.ts +33 -5
  607. package/src/scripts/probe_turnaround.ts +183 -3
  608. package/src/scripts/project_thin_rules.ts +34 -327
  609. package/src/scripts/ratification_header.ts +77 -0
  610. package/src/scripts/refusal_envelope.ts +138 -0
  611. package/src/scripts/release_publication.ts +29 -3
  612. package/src/scripts/report_dispatch_import_closure.ts +76 -0
  613. package/src/scripts/report_evidence_temperature.ts +657 -0
  614. package/src/scripts/report_installed_rule_links.ts +274 -0
  615. package/src/scripts/report_label_agreement.ts +233 -0
  616. package/src/scripts/report_module_reach.ts +212 -0
  617. package/src/scripts/report_obligation_mechanism.ts +228 -0
  618. package/src/scripts/report_parked_blockers.ts +222 -0
  619. package/src/scripts/report_required_checks_drift.ts +196 -0
  620. package/src/scripts/report_single_token_triggers.ts +277 -0
  621. package/src/scripts/report_skill_ranker_confusion.ts +543 -0
  622. package/src/scripts/report_standing_payload_by_host.ts +188 -15
  623. package/src/scripts/report_verification_record_coverage.ts +306 -0
  624. package/src/scripts/routing_doctor.ts +2 -2
  625. package/src/scripts/rule_activation_census.ts +5 -2
  626. package/src/scripts/rule_trigger_eval.ts +9 -9
  627. package/src/scripts/schemas/agent-settings.schema.json +17 -31
  628. package/src/scripts/schemas/command.schema.json +1 -1
  629. package/src/scripts/schemas/review-findings.schema.json +3 -2
  630. package/src/scripts/schemas/rule.schema.json +5 -0
  631. package/src/scripts/schemas/skill.schema.json +1 -1
  632. package/src/scripts/self_review_gate.ts +101 -9
  633. package/src/scripts/skill_tools/score_skill_relevance.ts +314 -40
  634. package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
  635. package/src/scripts/sync_gitignore.ts +29 -235
  636. package/src/scripts/sync_pr_branch.ts +403 -132
  637. package/src/scripts/trigger_eval_grandfather.json +0 -21
  638. package/src/server/schemas/settings.ts +42 -176
  639. package/src/shared/skillRanking.ts +169 -14
  640. package/dist/cli-delegate/chunk-5R7HOLAF.js +0 -99
  641. package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
  642. package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
  643. package/src/scripts/_lib/config_chain.ts +0 -477
  644. package/src/scripts/_lib/conformance_report.ts +0 -403
  645. package/src/scripts/_lib/eval_discrimination.ts +0 -95
  646. package/src/scripts/_lib/evaluator_promotion.ts +0 -225
  647. package/src/scripts/_lib/file_slicer.ts +0 -117
  648. package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
  649. package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
  650. package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
  651. package/src/scripts/_lib/role_split.ts +0 -338
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Measures the convention an existing history already follows, so a project
3
+ * with no declaration is offered its own format instead of the shipped default.
4
+ *
5
+ * The core is pure — commits, branch names and merge subjects in, a verdict
6
+ * out — and the thresholds live here as constants: the reference page renders
7
+ * them from this module, so the bar a reader sees is the bar the code applies.
8
+ * `readHistory` is the one function that runs git.
9
+ *
10
+ * Every figure is a policy heuristic (council 2026-09-04), not a statistically
11
+ * derived threshold.
12
+ */
13
+ import { spawnSync } from 'node:child_process';
14
+
15
+ import { invalidReason } from './git_convention.js';
16
+ import { makeTargetDeps } from './git_convention_carrier.js';
17
+ import { classifySubject, COMMIT_TYPES, TICKET_GRAMMAR, type CommitFormat, type SubjectFamily } from './git_convention_grammar.js';
18
+
19
+ export const MEASURE_LIMIT = 200;
20
+ export const MEASURE_SINCE = '24 months ago';
21
+ export const MIN_N = 30;
22
+ /** The newest eligible commits read on their own for a recent switch the halves still average away. */
23
+ export const RECENT_WINDOW = MIN_N;
24
+ /** With three or more human authors, over the per-author-capped sample. */
25
+ export const SHARE_BAR = 0.8;
26
+ /** With one or two authors, uncapped: a cap of 20 would put `MIN_N` out of reach. */
27
+ export const SMALL_TEAM_SHARE_BAR = 0.9;
28
+ export const MIN_CAPPED_AUTHORS = 3;
29
+ export const AUTHOR_CAP_PER_HALF = 20;
30
+ export const BULK_IMPORT_FILES = 500;
31
+ /** Merged branches are usually deleted, so far fewer names survive than commits. */
32
+ export const MIN_BRANCHES = 10;
33
+ /** The revision of the families and exclusions; a card measured under another one is re-measured. */
34
+ export const CLASSIFIER_VERSION = '2026-10-06';
35
+
36
+ export const BOT_AUTHOR = /\[bot\]|dependabot|renovate|github-actions|semantic-release|release-please/i;
37
+ export const AUTOMATION_SUBJECT = /^Revert |^Merge |^chore\(release\)|^Bump |^v?\d+\.\d+\.\d+$/;
38
+
39
+ export interface HistoryCommit {
40
+ author: string;
41
+ email: string;
42
+ subject: string;
43
+ /** Files the commit touched, or null when unknown. */
44
+ files: number | null;
45
+ }
46
+
47
+ export interface FamilyShare {
48
+ family: SubjectFamily | 'other';
49
+ count: number;
50
+ share: number;
51
+ }
52
+
53
+ export interface HalfReading {
54
+ n: number;
55
+ family: SubjectFamily | 'other' | null;
56
+ share: number;
57
+ }
58
+
59
+ export interface SubjectMeasurement {
60
+ eligible: number;
61
+ excluded: { bots: number; automation: number; bulk: number };
62
+ authors: number;
63
+ capped: boolean;
64
+ cappedTotal: number;
65
+ bar: number;
66
+ families: FamilyShare[];
67
+ newer: HalfReading;
68
+ older: HalfReading;
69
+ halvesAgree: boolean;
70
+ /** The newest `RECENT_WINDOW` eligible commits, capped per author like the halves. */
71
+ recent: HalfReading;
72
+ /** Which reading showed the switch when `migrating`. */
73
+ migratedBy: 'newer-half' | 'recent-window' | null;
74
+ /** The family to propose, or null below the bar. */
75
+ established: SubjectFamily | null;
76
+ /** True when the newer half, or the newest window, clears the bar on a family other than the history's dominant one. */
77
+ migrating: boolean;
78
+ /** Why the history is below the bar; empty when a family is established. */
79
+ reasons: string[];
80
+ /** The two strongest families with a grammar, strongest first. */
81
+ strongest: SubjectFamily[];
82
+ }
83
+
84
+ function _key(c: HistoryCommit): string {
85
+ return (c.email || c.author).toLowerCase();
86
+ }
87
+
88
+ function _cap(commits: readonly HistoryCommit[]): HistoryCommit[] {
89
+ const seen = new Map<string, number>();
90
+ return commits.filter((c) => {
91
+ const k = _key(c);
92
+ const n = (seen.get(k) ?? 0) + 1;
93
+ seen.set(k, n);
94
+ return n <= AUTHOR_CAP_PER_HALF;
95
+ });
96
+ }
97
+
98
+ function _shares(commits: readonly HistoryCommit[]): FamilyShare[] {
99
+ const counts = new Map<SubjectFamily | 'other', number>();
100
+ for (const c of commits) {
101
+ const f = classifySubject(c.subject);
102
+ counts.set(f, (counts.get(f) ?? 0) + 1);
103
+ }
104
+ const total = commits.length;
105
+ return [...counts.entries()]
106
+ .map(([family, count]) => ({ family, count, share: total === 0 ? 0 : count / total }))
107
+ .sort((a, b) => b.count - a.count || a.family.localeCompare(b.family));
108
+ }
109
+
110
+ function _half(commits: readonly HistoryCommit[]): HalfReading {
111
+ const top = _shares(commits)[0];
112
+ return { n: commits.length, family: top?.family ?? null, share: top?.share ?? 0 };
113
+ }
114
+
115
+ function _clears(n: number, top: FamilyShare | HalfReading | undefined, bar: number): top is FamilyShare | HalfReading {
116
+ return n >= MIN_N && top !== undefined && top.family !== null && top.family !== 'other' && top.share >= bar;
117
+ }
118
+
119
+ /** `commits` newest first, as `git log` prints them. */
120
+ export function measureSubjects(commits: readonly HistoryCommit[]): SubjectMeasurement {
121
+ const excluded = { bots: 0, automation: 0, bulk: 0 };
122
+ const eligible = commits.filter((c) => {
123
+ if (BOT_AUTHOR.test(c.author) || BOT_AUTHOR.test(c.email)) excluded.bots++;
124
+ else if (AUTOMATION_SUBJECT.test(c.subject)) excluded.automation++;
125
+ else if (c.files !== null && c.files > BULK_IMPORT_FILES) excluded.bulk++;
126
+ else return true;
127
+ return false;
128
+ });
129
+ const authors = new Set(eligible.map(_key)).size;
130
+ const capped = authors >= MIN_CAPPED_AUTHORS;
131
+ const bar = capped ? SHARE_BAR : SMALL_TEAM_SHARE_BAR;
132
+ // Split before capping: a cap over the whole sample lets one author's
133
+ // newest commits fill the quota and empty the older half.
134
+ const cut = Math.ceil(eligible.length / 2);
135
+ const newerRaw = eligible.slice(0, cut);
136
+ const olderRaw = eligible.slice(cut);
137
+ const newerSample = capped ? _cap(newerRaw) : newerRaw;
138
+ const olderSample = capped ? _cap(olderRaw) : olderRaw;
139
+ const sample = [...newerSample, ...olderSample];
140
+ const families = _shares(sample);
141
+ const newer = _half(newerSample);
142
+ const older = _half(olderSample);
143
+ const halvesAgree = newer.family !== null && newer.family === older.family;
144
+ const recent = _half((capped ? _cap(eligible) : eligible).slice(0, RECENT_WINDOW));
145
+ const top = families[0];
146
+
147
+ let established: SubjectFamily | null = null;
148
+ let migrating = false;
149
+ let migratedBy: SubjectMeasurement['migratedBy'] = null;
150
+ const reasons: string[] = [];
151
+ if (eligible.length < MIN_N) reasons.push(`n ${eligible.length} < ${MIN_N}`);
152
+ if (top === undefined || top.family === 'other') reasons.push('no family with a grammar leads');
153
+ else if (top.share < bar) reasons.push(`${top.family} at ${pct(top.share)} < ${pct(bar)}`);
154
+ if (!halvesAgree && eligible.length > 0) reasons.push(`the halves disagree (newer ${newer.family ?? '—'}, older ${older.family ?? '—'})`);
155
+ if (reasons.length === 0 && top !== undefined) established = top.family as SubjectFamily;
156
+ else if (!halvesAgree && _clears(newer.n, newer, bar)) {
157
+ established = newer.family as SubjectFamily;
158
+ migrating = true;
159
+ migratedBy = 'newer-half';
160
+ }
161
+ // A switch younger than half the sample: both halves still read the old
162
+ // family, so only the newest window shows the history has moved on.
163
+ if (!migrating && recent.n >= RECENT_WINDOW && recent.family !== top?.family && _clears(recent.n, recent, bar)) {
164
+ established = recent.family as SubjectFamily;
165
+ migrating = true;
166
+ migratedBy = 'recent-window';
167
+ reasons.push(`the newest ${recent.n} read ${recent.family} at ${pct(recent.share)}, not ${top?.family ?? '—'}`);
168
+ }
169
+ return {
170
+ eligible: eligible.length,
171
+ excluded,
172
+ authors,
173
+ capped,
174
+ cappedTotal: sample.length,
175
+ bar,
176
+ families,
177
+ newer,
178
+ older,
179
+ halvesAgree,
180
+ recent,
181
+ migratedBy,
182
+ established,
183
+ migrating,
184
+ reasons: established === null || migrating ? reasons : [],
185
+ strongest: families.filter((f) => f.family !== 'other').slice(0, 2).map((f) => f.family as SubjectFamily),
186
+ };
187
+ }
188
+
189
+ export type BranchShape = '{type}/{ticket}-{slug}' | '{type}/{ticket}/{slug}' | '{ticket}-{slug}' | '{ticket}/{slug}' | '{type}/{slug}';
190
+
191
+ const BRANCH_TYPES = [...COMMIT_TYPES, 'feature', 'bugfix', 'hotfix'].join('|');
192
+ const BRANCH_SHAPES: ReadonlyArray<readonly [BranchShape, RegExp]> = [
193
+ ['{type}/{ticket}-{slug}', new RegExp(`^(${BRANCH_TYPES})/${TICKET_GRAMMAR}-[^/]+$`)],
194
+ ['{type}/{ticket}/{slug}', new RegExp(`^(${BRANCH_TYPES})/${TICKET_GRAMMAR}/[^/]+$`)],
195
+ ['{ticket}-{slug}', new RegExp(`^${TICKET_GRAMMAR}-[^/]+$`)],
196
+ ['{ticket}/{slug}', new RegExp(`^${TICKET_GRAMMAR}/[^/]+$`)],
197
+ ['{type}/{slug}', new RegExp(`^(${BRANCH_TYPES})/[^/]+$`)],
198
+ ];
199
+ const BOT_BRANCH = /^(dependabot|renovate|release-please)[/-]/;
200
+
201
+ export interface BranchMeasurement {
202
+ sampled: number;
203
+ shapes: { shape: BranchShape | 'other'; count: number; share: number }[];
204
+ /** A pattern the reader accepts, or null when no shape clears the bar. */
205
+ pattern: BranchShape | null;
206
+ share: number;
207
+ }
208
+
209
+ export function classifyBranch(name: string): BranchShape | 'other' {
210
+ return BRANCH_SHAPES.find(([, re]) => re.test(name))?.[0] ?? 'other';
211
+ }
212
+
213
+ /** Branch names without their remote prefix; the default branch and bots already excluded by the caller or here. */
214
+ export function measureBranches(names: readonly string[]): BranchMeasurement {
215
+ const sample = names.filter((n) => !BOT_BRANCH.test(n));
216
+ const counts = new Map<BranchShape | 'other', number>();
217
+ for (const n of sample) {
218
+ const s = classifyBranch(n);
219
+ counts.set(s, (counts.get(s) ?? 0) + 1);
220
+ }
221
+ const shapes = [...counts.entries()]
222
+ .map(([shape, count]) => ({ shape, count, share: count / sample.length }))
223
+ .sort((a, b) => b.count - a.count || a.shape.localeCompare(b.shape));
224
+ const top = shapes[0];
225
+ const clear = top !== undefined && top.shape !== 'other' && sample.length >= MIN_BRANCHES && top.share >= SHARE_BAR
226
+ && invalidReason('branch_pattern', top.shape) === null;
227
+ return { sampled: sample.length, shapes, pattern: clear ? (top.shape as BranchShape) : null, share: top?.share ?? 0 };
228
+ }
229
+
230
+ export interface UpdateStyle {
231
+ merges: number;
232
+ baseMerges: number;
233
+ observed: 'merge' | 'linear';
234
+ }
235
+
236
+ /** Merges of the default branch into a topic branch, read from their default subjects. */
237
+ export function measureUpdateStyle(mergeSubjects: readonly string[], defaultBranch: string): UpdateStyle {
238
+ const name = defaultBranch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
239
+ const base = new RegExp(`^Merge (remote-tracking )?branch '(origin/)?${name}'`);
240
+ const baseMerges = mergeSubjects.filter((s) => base.test(s)).length;
241
+ return { merges: mergeSubjects.length, baseMerges, observed: baseMerges > 0 ? 'merge' : 'linear' };
242
+ }
243
+
244
+ /** The `git.commit_format` value a family maps to, or null when it maps to none. */
245
+ export function formatForFamily(family: SubjectFamily): CommitFormat | null {
246
+ if (family === 'conventional') return 'ticket-scope';
247
+ if (family === 'ticket-conventional') return 'ticket-conventional';
248
+ return null;
249
+ }
250
+
251
+ /** The `.git-convention.yml` content for a choice, or null when neither key has a value. `update_strategy` is never written. */
252
+ export function teamFile(family: SubjectFamily | null, pattern: BranchShape | null): string | null {
253
+ const format = family === null ? null : formatForFamily(family);
254
+ if (format === null && pattern === null) return null;
255
+ return ['git:', ...(format === null ? [] : [` commit_format: ${format}`]), ...(pattern === null ? [] : [` branch_pattern: "${pattern}"`]), ''].join('\n');
256
+ }
257
+
258
+ export function pct(x: number): string {
259
+ return `${Math.round(x * 100)} %`;
260
+ }
261
+
262
+ function _git(cwd: string, args: readonly string[]): string | null {
263
+ const r = spawnSync('git', args, { cwd, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
264
+ return r.status === 0 ? r.stdout : null;
265
+ }
266
+
267
+ export interface History {
268
+ trunk: string;
269
+ defaultBranch: string;
270
+ commits: HistoryCommit[];
271
+ branches: string[];
272
+ mergeSubjects: string[];
273
+ /** True when `MEASURE_SINCE` yielded fewer than `MIN_N` commits and the newest ones were read regardless of age. */
274
+ windowExtended: boolean;
275
+ }
276
+
277
+ /** No default branch could be resolved, so nothing was sampled; `reason` says why. */
278
+ export interface TrunkUnresolved {
279
+ unresolved: string;
280
+ }
281
+
282
+ /**
283
+ * The default branch as the carrier resolves it, or why there is none. A
284
+ * branch name guessed in its place (`main`, `master`, the current `HEAD`)
285
+ * samples another history and proposes a convention from it.
286
+ */
287
+ function _trunk(cwd: string): { trunk: string; remote: string; name: string } | TrunkUnresolved {
288
+ const ref = makeTargetDeps(cwd).defaultBranch();
289
+ if (ref === null) {
290
+ return { unresolved: 'no default branch could be resolved — origin names none and refs/remotes/origin/HEAD is not set' };
291
+ }
292
+ if (_git(cwd, ['rev-parse', '-q', '--verify', `${ref}^{commit}`]) === null) {
293
+ return { unresolved: `the default branch ${ref} is not in this checkout — fetch it first` };
294
+ }
295
+ const slash = ref.indexOf('/');
296
+ return { trunk: ref, remote: ref.slice(0, slash), name: ref.slice(slash + 1) };
297
+ }
298
+
299
+ /**
300
+ * The sample `measureSubjects`, `measureBranches` and `measureUpdateStyle` read,
301
+ * `TrunkUnresolved` without a default branch, or null outside a git repository.
302
+ */
303
+ export function readHistory(cwd: string, limit = MEASURE_LIMIT): History | TrunkUnresolved | null {
304
+ if (_git(cwd, ['rev-parse', '--git-dir']) === null) return null;
305
+ const t = _trunk(cwd);
306
+ if ('unresolved' in t) return t;
307
+ const read = (since: readonly string[]): HistoryCommit[] =>
308
+ (_git(cwd, ['log', t.trunk, '--no-merges', '-n', String(limit), ...since, '--pretty=format:%x1e%aN%x09%aE%x09%s', '--shortstat']) ?? '')
309
+ .split('\x1e')
310
+ .filter((r) => r.trim() !== '')
311
+ .map((r) => {
312
+ const [head = '', ...rest] = r.split('\n');
313
+ const [author = '', email = '', ...subject] = head.split('\t');
314
+ const stat = /(\d+) files? changed/.exec(rest.join('\n'));
315
+ return { author, email, subject: subject.join('\t'), files: stat === null ? null : Number(stat[1]) };
316
+ });
317
+ // A quiet or archived project has its convention in older commits; a
318
+ // window that samples nothing would report "below the bar" for a history
319
+ // that states its format plainly.
320
+ let commits = read([`--since=${MEASURE_SINCE}`]);
321
+ let windowExtended = false;
322
+ if (commits.length < MIN_N) {
323
+ const all = read([]);
324
+ windowExtended = all.length > commits.length;
325
+ if (windowExtended) commits = all;
326
+ }
327
+ const refs = _git(cwd, ['for-each-ref', '--format=%(refname:short)', 'refs/remotes']) ?? '';
328
+ const branches = refs
329
+ .split('\n')
330
+ .map((r) => r.trim())
331
+ .filter((r) => r !== '' && r.includes('/'))
332
+ .map((r) => ({ remote: r.slice(0, r.indexOf('/')), name: r.slice(r.indexOf('/') + 1) }))
333
+ .filter((b) => b.name !== 'HEAD' && !(b.name === t.name && b.remote === t.remote))
334
+ .map((b) => b.name);
335
+ const merges = _git(cwd, ['log', '--all', '--merges', '-n', String(limit), `--since=${MEASURE_SINCE}`, '--pretty=format:%s']) ?? '';
336
+ return {
337
+ trunk: t.trunk,
338
+ defaultBranch: t.name,
339
+ commits,
340
+ branches,
341
+ mergeSubjects: merges.split('\n').filter((s) => s !== ''),
342
+ windowExtended,
343
+ };
344
+ }
@@ -0,0 +1,314 @@
1
+ /**
2
+ * The `.gitignore` managed-block logic, with no CLI entry.
3
+ *
4
+ * WHY IT IS NOT IN `sync_gitignore.ts` ANY MORE. That file ends in a
5
+ * `process.exit(main(...))` behind a CLI-entry guard, and `check_installer_import_purity`
6
+ * refuses any module-level exit reachable from `install.ts`: esbuild inlines the
7
+ * whole closure into `dist/install/install.mjs`, where the guard comparing
8
+ * `import.meta.url` to `process.argv[1]` evaluates TRUE because the bundle IS
9
+ * argv[1]. A consumer install would then exit after writing its payload.
10
+ *
11
+ * So the pure half lives here, with no entry and no exit, and `sync_gitignore.ts`
12
+ * re-exports every name it used to own — the CLI contract and the ported
13
+ * pytest suite's snake_case call sites are unchanged.
14
+ *
15
+ * Everything below is byte-for-byte the behaviour it had in that file,
16
+ * including the historical quirks downstream consumers pin.
17
+ */
18
+ import * as fs from 'node:fs';
19
+ import * as path from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+
22
+ export const SECTION_HEADER = '# event4u/agent-config';
23
+ export const SECTION_FOOTER = '# event4u/agent-config — END';
24
+ export const DEFAULT_GITIGNORE = '.gitignore';
25
+
26
+ const _HERE = fileURLToPath(import.meta.url);
27
+ // _HERE === <repo>/src/scripts/_lib/gitignore_block.ts, so the repo root is
28
+ // three directories up. The retired Python implementation derived
29
+ // DEFAULT_TEMPLATE = <file>.parent.parent.parent / "src" / "config" /
30
+ // "gitignore-block.txt" from one level higher; the extra `..` here is that
31
+ // same root reached from one level deeper.
32
+ export const DEFAULT_TEMPLATE = path.join(
33
+ path.dirname(_HERE),
34
+ '..',
35
+ '..',
36
+ '..',
37
+ 'src',
38
+ 'config',
39
+ 'gitignore-block.txt',
40
+ );
41
+
42
+ // Legacy patterns that lived in older versions of src/config/gitignore-block.txt
43
+ // before runtime artefacts moved under /agents/runtime/ (May 2026). They get
44
+ // stripped wherever they appear in the consumer's .gitignore — inside the
45
+ // managed block or outside (older installers / hand-edits). Current canonical
46
+ // equivalents (e.g. /agents/runtime/.agent-prices.md) come from the template
47
+ // and are NOT affected. Leading-slash variants are matched defensively.
48
+ //
49
+ // Authoritative source: src/config/agents-paths.yml entries with `legacy: true`.
50
+ // Manual sync until the generation step from the manifest is implemented
51
+ // (road-to-agents-dir-and-gitignore-hygiene Phase 3.2 follow-on).
52
+ export const LEGACY_PATTERNS: readonly string[] = [
53
+ '.agent-chat-history',
54
+ '.agent-chat-history.bak',
55
+ '.agent-chat-history.*.bak',
56
+ '.agent-prices.md',
57
+ '.council-tmp/',
58
+ // 2.x intermediate: prices cache lived directly under agents/ before
59
+ // consolidating under agents/runtime/.
60
+ 'agents/.agent-prices.md',
61
+ // Budget history JSONLs — previously listed explicitly at project
62
+ // root or under agents/; now covered by the /agents/runtime/
63
+ // catch-all in the managed block.
64
+ '.augment-budget-history.jsonl',
65
+ '.rule-budget-history.jsonl',
66
+ 'agents/.augment-budget-history.jsonl',
67
+ 'agents/.rule-budget-history.jsonl',
68
+ ];
69
+
70
+ export function _strip(ln: string): string {
71
+ // Python: ln.rstrip("\n").rstrip() — strip a trailing newline, then strip
72
+ // all trailing whitespace.
73
+ return ln.replace(/\n+$/, '').replace(/\s+$/, '');
74
+ }
75
+
76
+ export function _is_entry(ln: string): boolean {
77
+ // Non-empty, non-comment line = a path/pattern entry.
78
+ const s = _strip(ln).replace(/^\s+/, '');
79
+ return Boolean(s) && !s.startsWith('#');
80
+ }
81
+
82
+ /** Error raised when the template file is missing (→ exit 2 in main). */
83
+ export class TemplateNotFoundError extends Error {
84
+ constructor(p: string) {
85
+ super(`template not found: ${p}`);
86
+ this.name = 'TemplateNotFoundError';
87
+ }
88
+ }
89
+
90
+ export function _isFile(p: string): boolean {
91
+ try {
92
+ return fs.statSync(p).isFile();
93
+ } catch {
94
+ return false;
95
+ }
96
+ }
97
+
98
+ /** Python str.splitlines() — split on universal newlines, no trailing empty. */
99
+ export function _splitlines(text: string): string[] {
100
+ if (text === '') return [];
101
+ // str.splitlines() splits on \n, \r, \r\n (and more) and does NOT keep a
102
+ // trailing empty element. The targets here only ever contain \n / \r\n.
103
+ const parts = text.split(/\r\n|\r|\n/);
104
+ if (parts.length > 0 && parts[parts.length - 1] === '') parts.pop();
105
+ return parts;
106
+ }
107
+
108
+ export function load_template(p: string): string[] {
109
+ if (!_isFile(p)) {
110
+ throw new TemplateNotFoundError(p);
111
+ }
112
+ const text = fs.readFileSync(p, 'utf-8');
113
+ // Keep trailing newlines stripped; we splice explicit newlines.
114
+ return _splitlines(text).map(_strip);
115
+ }
116
+
117
+ /**
118
+ * Locate the managed block; return [start_idx, end_idx_exclusive] or null.
119
+ *
120
+ * `start_idx` points at the SECTION_HEADER line.
121
+ * `end_idx_exclusive` points one past the last line of the block.
122
+ * Honors explicit SECTION_FOOTER when present; otherwise treats the
123
+ * block as extending to EOF or to the next non-managed section.
124
+ */
125
+ export function find_block(lines: readonly string[]): [number, number] | null {
126
+ for (let i = 0; i < lines.length; i += 1) {
127
+ if (_strip(lines[i] as string) === SECTION_HEADER) {
128
+ const start = i;
129
+ // Explicit footer?
130
+ for (let j = i + 1; j < lines.length; j += 1) {
131
+ if (_strip(lines[j] as string) === SECTION_FOOTER) {
132
+ return [start, j + 1];
133
+ }
134
+ }
135
+ // Legacy: extend to EOF or next non-managed section break.
136
+ let end = lines.length;
137
+ for (let j = i + 1; j < lines.length; j += 1) {
138
+ const s = _strip(lines[j] as string).replace(/^\s+/, '');
139
+ if (
140
+ s.startsWith('#') &&
141
+ !s.startsWith('# Agent config') &&
142
+ s !== SECTION_HEADER
143
+ ) {
144
+ end = j;
145
+ while (end > i + 1 && _strip(lines[end - 1] as string) === '') {
146
+ end -= 1;
147
+ }
148
+ break;
149
+ }
150
+ }
151
+ return [start, end];
152
+ }
153
+ }
154
+ return null;
155
+ }
156
+
157
+ /** Return entries (paths/patterns) present in the given block. */
158
+ export function block_entries(block_lines: readonly string[]): string[] {
159
+ return block_lines
160
+ .filter((ln) => _is_entry(ln))
161
+ .map((ln) => _strip(ln).replace(/^\s+/, ''));
162
+ }
163
+
164
+ export function template_entries(template_lines: readonly string[]): string[] {
165
+ return template_lines.filter((ln) => _is_entry(ln)).map((ln) => ln.replace(/^\s+/, ''));
166
+ }
167
+
168
+ /** Return a fresh, fully-managed block with START + body + END. */
169
+ export function build_fresh_block(template_lines: readonly string[]): string[] {
170
+ return [SECTION_HEADER, ...template_lines, SECTION_FOOTER];
171
+ }
172
+
173
+ /**
174
+ * Return [new_lines, added_entries].
175
+ *
176
+ * - If block missing: append fresh block (preceded by a blank line if the
177
+ * file's last line is not already empty).
178
+ * - If block present and replace=true: rewrite block in full.
179
+ * - If block present and replace=false: append any missing managed entries
180
+ * before the END marker (adding END if absent). User-added lines inside the
181
+ * block are preserved.
182
+ */
183
+ export function sync_block(
184
+ existing_lines: readonly string[],
185
+ template_lines: readonly string[],
186
+ options: { replace?: boolean } = {},
187
+ ): [string[], string[]] {
188
+ const replace = options.replace ?? false;
189
+ const loc = find_block(existing_lines);
190
+ const fresh = build_fresh_block(template_lines);
191
+
192
+ // Missing block → append with leading blank if needed.
193
+ if (loc === null) {
194
+ const newLines = [...existing_lines];
195
+ if (newLines.length > 0 && _strip(newLines[newLines.length - 1] as string) !== '') {
196
+ newLines.push('');
197
+ }
198
+ newLines.push(...fresh);
199
+ return [newLines, template_entries(template_lines)];
200
+ }
201
+
202
+ const [start, end] = loc;
203
+ const head = existing_lines.slice(0, start);
204
+ let block = existing_lines.slice(start, end);
205
+ const tail = existing_lines.slice(end);
206
+
207
+ if (replace) {
208
+ const existing = new Set(block_entries(block));
209
+ const added = template_entries(template_lines).filter((e) => !existing.has(e));
210
+ return [[...head, ...fresh, ...tail], added];
211
+ }
212
+
213
+ // Append-only mode.
214
+ const existing_entries = new Set(block_entries(block));
215
+ const missing = template_entries(template_lines).filter((e) => !existing_entries.has(e));
216
+ if (missing.length === 0) {
217
+ return [[...existing_lines], []];
218
+ }
219
+
220
+ // Ensure block ends with SECTION_FOOTER; insert missing entries right
221
+ // before it.
222
+ let insert_at: number;
223
+ if (block.length > 0 && _strip(block[block.length - 1] as string) === SECTION_FOOTER) {
224
+ insert_at = block.length - 1;
225
+ } else {
226
+ block = [...block, SECTION_FOOTER];
227
+ insert_at = block.length - 1;
228
+ }
229
+ const new_block = [...block.slice(0, insert_at), ...missing, ...block.slice(insert_at)];
230
+ return [[...head, ...new_block, ...tail], missing];
231
+ }
232
+
233
+ /**
234
+ * Strip legacy entries from anywhere in the file.
235
+ *
236
+ * A line is legacy when its stripped, leading-whitespace-trimmed content
237
+ * matches a `LEGACY_PATTERNS` entry — with or without a leading slash.
238
+ * Comments and blank lines are untouched; current managed entries (e.g.
239
+ * `/agents/.agent-chat-history`) are not in the legacy set and survive.
240
+ */
241
+ export function cleanup_legacy(lines: readonly string[]): [string[], string[]] {
242
+ const legacy = new Set(LEGACY_PATTERNS);
243
+ const kept: string[] = [];
244
+ const removed: string[] = [];
245
+ for (const ln of lines) {
246
+ const s = _strip(ln).replace(/^\s+/, '');
247
+ if (legacy.has(s) || (s.startsWith('/') && legacy.has(s.slice(1)))) {
248
+ removed.push(s);
249
+ continue;
250
+ }
251
+ kept.push(ln);
252
+ }
253
+ return [kept, removed];
254
+ }
255
+
256
+ /** Join lines with newlines and enforce exactly one trailing newline. */
257
+ export function format_file(lines: readonly string[]): string {
258
+ const text = lines.join('\n');
259
+ return text.replace(/\n+$/, '') + '\n';
260
+ }
261
+
262
+ /**
263
+ * Write the managed block into a project that has no wizard to do it.
264
+ *
265
+ * WHY IT EXISTS. The block is normally installed by `refresh --project` /
266
+ * `sync:gitignore`, which the browser wizard reaches. A `--no-ui` install
267
+ * reaches neither, so a headless consumer ended up with a package that writes
268
+ * dispatcher state under `agents/` and a `.gitignore` that says nothing about
269
+ * it: `git status` fills with untracked runtime files the developer did not
270
+ * create and cannot place.
271
+ *
272
+ * APPEND-ONLY, NEVER `replace`. A line a developer put inside the block is
273
+ * theirs; this adds the managed entries that are missing and touches nothing
274
+ * else.
275
+ *
276
+ * BEST-EFFORT THROUGHOUT. No `.gitignore` and no git repository, an unreadable
277
+ * template, an unwritable file — each returns 0 quietly. An installer that
278
+ * failed because it could not tidy a listing would be worse than the listing.
279
+ *
280
+ * Returns the number of entries added (0 when nothing changed), and writes
281
+ * nothing when `dry_run`. Reporting is the caller's: this module owns no
282
+ * output convention.
283
+ */
284
+ export function write_managed_block(project_root: string, dry_run: boolean): number {
285
+ const target = path.join(project_root, DEFAULT_GITIGNORE);
286
+ let template: string[];
287
+ try {
288
+ template = load_template(DEFAULT_TEMPLATE);
289
+ } catch {
290
+ return 0;
291
+ }
292
+ let existing: string[] = [];
293
+ if (_isFile(target)) {
294
+ existing = _splitlines(fs.readFileSync(target, 'utf-8'));
295
+ } else if (!_isFile(path.join(project_root, '.git')) && !_isDir(path.join(project_root, '.git'))) {
296
+ return 0;
297
+ }
298
+ const [lines, added] = sync_block(existing, template);
299
+ if (added.length === 0 || dry_run) return added.length;
300
+ try {
301
+ fs.writeFileSync(target, format_file(lines), 'utf-8');
302
+ } catch {
303
+ return 0;
304
+ }
305
+ return added.length;
306
+ }
307
+
308
+ function _isDir(p: string): boolean {
309
+ try {
310
+ return fs.statSync(p).isDirectory();
311
+ } catch {
312
+ return false;
313
+ }
314
+ }