@event4u/agent-config 16.4.0 → 17.0.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 (1052) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +2 -2
  4. package/.claude-plugin/skills/install-agent-config/SKILL.md +4 -4
  5. package/CHANGELOG.md +483 -669
  6. package/CONTRIBUTING.md +47 -0
  7. package/README.md +25 -25
  8. package/dist/agent-src/commands/{design.md → agent-design.md} +11 -7
  9. package/dist/agent-src/commands/agents/init.md +66 -3
  10. package/dist/agent-src/commands/agents/user/init.md +3 -0
  11. package/dist/agent-src/commands/{optimize/deep.md → analyze/and-optimize.md} +72 -33
  12. package/dist/agent-src/commands/analyze/inbox.md +168 -37
  13. package/dist/agent-src/commands/analyze/pr.md +144 -0
  14. package/dist/agent-src/commands/analyze/{repo.md → reference.md} +85 -14
  15. package/dist/agent-src/commands/analyze/roadmap-repos.md +19 -10
  16. package/dist/agent-src/commands/analyze.md +28 -12
  17. package/dist/agent-src/commands/audit.md +115 -0
  18. package/dist/agent-src/commands/brand/review.md +13 -2
  19. package/dist/agent-src/commands/brand/tokens.md +3 -3
  20. package/dist/agent-src/commands/brand/voice.md +8 -5
  21. package/dist/agent-src/commands/brand.md +2 -2
  22. package/dist/agent-src/commands/challenge-me/closure.md +25 -0
  23. package/dist/agent-src/commands/design-system/import.md +8 -3
  24. package/dist/agent-src/commands/design-system/sync.md +98 -0
  25. package/dist/agent-src/commands/design-system.md +6 -1
  26. package/dist/agent-src/commands/evals/analyze.json +44 -0
  27. package/dist/agent-src/commands/evals/audit.json +12 -0
  28. package/dist/agent-src/commands/evals/retro.json +12 -0
  29. package/dist/agent-src/commands/fix/ci.md +10 -8
  30. package/dist/agent-src/commands/ghostwriter/write.md +22 -0
  31. package/dist/agent-src/commands/memory/learn-low-impact.md +70 -83
  32. package/dist/agent-src/commands/memory/propose.md +12 -0
  33. package/dist/agent-src/commands/memory.md +1 -1
  34. package/dist/agent-src/commands/optimize.md +4 -3
  35. package/dist/agent-src/commands/post-as/me.md +18 -0
  36. package/dist/agent-src/commands/pr/create.md +17 -342
  37. package/dist/agent-src/commands/pr/merge.md +129 -368
  38. package/dist/agent-src/commands/retro.md +121 -0
  39. package/dist/agent-src/commands/review/routing.md +1 -1
  40. package/dist/agent-src/commands/roadmap/next.md +4 -1
  41. package/dist/agent-src/commands/roadmap/process-full.md +46 -333
  42. package/dist/agent-src/commands/roadmap/triage-parked.md +6 -2
  43. package/dist/agent-src/commands/team-knowledge/consolidate.md +2 -2
  44. package/dist/agent-src/commands/team-knowledge.md +1 -1
  45. package/dist/agent-src/commands/threat-model.md +1 -1
  46. package/dist/agent-src/commands/upstream-contribute.md +91 -101
  47. package/dist/agent-src/commands/worktree/cleanup.md +18 -11
  48. package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +54 -0
  49. package/dist/agent-src/contexts/execution/analysis-loop.md +137 -0
  50. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +3 -3
  51. package/dist/agent-src/contexts/execution/decision-closure-execution.md +1 -1
  52. package/dist/agent-src/contexts/execution/host-capability-manifest.md +6 -0
  53. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +11 -4
  54. package/dist/agent-src/contexts/execution/pr-create-branches-content.md +250 -0
  55. package/dist/agent-src/contexts/execution/pr-create-branches-freshness.md +150 -0
  56. package/dist/agent-src/contexts/execution/pr-merge-queue.md +287 -0
  57. package/dist/agent-src/contexts/execution/pr-merge-sync.md +276 -0
  58. package/dist/agent-src/contexts/execution/pr-merge-trust-boundary.md +69 -0
  59. package/dist/agent-src/contexts/execution/process-full-all.md +233 -0
  60. package/dist/agent-src/contexts/execution/process-full-delivery.md +231 -0
  61. package/dist/agent-src/contexts/execution/roadmap-execution-contract-branches.md +42 -0
  62. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -35
  63. package/dist/agent-src/contexts/execution/roadmap-process-loop-close.md +235 -0
  64. package/dist/agent-src/contexts/execution/roadmap-process-loop-prescan.md +216 -0
  65. package/dist/agent-src/contexts/execution/roadmap-process-loop-run.md +253 -0
  66. package/dist/agent-src/contexts/execution/roadmap-process-loop-set.md +212 -0
  67. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +25 -864
  68. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +14 -2
  69. package/dist/agent-src/contexts/execution/subagent-steering.md +65 -8
  70. package/dist/agent-src/contexts/model-recommendations.md +5 -5
  71. package/dist/agent-src/contexts/subagent-configuration.md +1 -1
  72. package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +4 -3
  73. package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +11 -5
  74. package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
  75. package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
  76. package/dist/agent-src/guidelines/design-antipatterns.md +6 -1
  77. package/dist/agent-src/guidelines/design-asset-discipline.md +17 -0
  78. package/dist/agent-src/guidelines/design-fidelity-routing.md +1 -0
  79. package/dist/agent-src/guidelines/php/api-design.md +10 -1
  80. package/dist/agent-src/rules/brand-source-of-truth.md +7 -6
  81. package/dist/agent-src/rules/code-provenance.md +1 -1
  82. package/dist/agent-src/rules/context-hygiene.md +0 -1
  83. package/dist/agent-src/rules/design-fidelity.md +12 -13
  84. package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
  85. package/dist/agent-src/rules/fix-what-you-see.md +1 -1
  86. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +14 -15
  87. package/dist/agent-src/rules/missing-skill-recovery.md +12 -11
  88. package/dist/agent-src/rules/neighbour-precedence.md +1 -1
  89. package/dist/agent-src/rules/recurring-criticism.md +1 -1
  90. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -2
  91. package/dist/agent-src/rules/self-repair-loop.md +2 -2
  92. package/dist/agent-src/rules/token-budget-discipline.md +2 -2
  93. package/dist/agent-src/scripts/dashboard_mode.ts +4 -1
  94. package/dist/agent-src/scripts/roadmap_age.ts +175 -0
  95. package/dist/agent-src/scripts/update_roadmap_progress.ts +10 -2
  96. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +3 -3
  97. package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
  98. package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
  99. package/dist/agent-src/skills/agent-security-review/SKILL.md +2 -2
  100. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +12 -4
  101. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +7 -0
  102. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +11 -1
  103. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +7 -0
  104. package/dist/agent-src/skills/ai-council/references/execution-modes.md +7 -0
  105. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +19 -0
  106. package/dist/agent-src/skills/ai-council/references/procedure.md +7 -0
  107. package/dist/agent-src/skills/api-design/SKILL.md +2 -2
  108. package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
  109. package/dist/agent-src/skills/authz-review/SKILL.md +5 -3
  110. package/dist/agent-src/skills/blade-ui/SKILL.md +2 -2
  111. package/dist/agent-src/skills/brand/SKILL.md +7 -3
  112. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +13 -6
  113. package/dist/agent-src/skills/brand-audit/SKILL.md +2 -1
  114. package/dist/agent-src/skills/brand-identity/SKILL.md +5 -4
  115. package/dist/agent-src/skills/brand-strategy/SKILL.md +5 -4
  116. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +18 -39
  117. package/dist/agent-src/skills/brand-to-tokens/templates/marp-brand-deck.md.example +2 -2
  118. package/dist/agent-src/skills/brand-to-tokens/templates/reveal-brand-deck.yaml +2 -2
  119. package/dist/agent-src/skills/canvas-design/SKILL.md +16 -4
  120. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  121. package/dist/agent-src/skills/composer-packages/SKILL.md +18 -0
  122. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  123. package/dist/agent-src/skills/content-funnel-design/SKILL.md +8 -1
  124. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  125. package/dist/agent-src/skills/context-document/SKILL.md +2 -2
  126. package/dist/agent-src/skills/corpus-grounding/SKILL.md +6 -6
  127. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +13 -11
  128. package/dist/agent-src/skills/corpus-grounding/scripts/ground.mjs +1706 -0
  129. package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.ts +7 -1
  130. package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
  131. package/dist/agent-src/skills/data-flow-mapper/SKILL.md +5 -2
  132. package/dist/agent-src/skills/database/SKILL.md +5 -4
  133. package/dist/agent-src/skills/decision-record/references/weighted-matrix.md +12 -0
  134. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -1
  135. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +61 -11
  136. package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
  137. package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
  138. package/dist/agent-src/skills/design-intelligence/data/landing.csv +1 -1
  139. package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +10 -2
  140. package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
  141. package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -3
  142. package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +25 -22
  143. package/dist/agent-src/skills/{wireframe → design-review}/references/story-beat-ledger.schema.json +1 -1
  144. package/dist/agent-src/skills/design-review/references/verification-automation.md +11 -3
  145. package/dist/agent-src/skills/design-system-capture/SKILL.md +15 -10
  146. package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -5
  147. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +2 -2
  148. package/dist/agent-src/skills/design-tokens/SKILL.md +23 -23
  149. package/dist/agent-src/skills/design-tokens/scripts/tokens.mjs +1037 -0
  150. package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +336 -13
  151. package/dist/agent-src/skills/design-tokens/templates/design-tokens-starter.json +52 -53
  152. package/dist/agent-src/skills/docker/SKILL.md +1 -1
  153. package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
  154. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -276
  155. package/dist/agent-src/skills/existing-ui-audit/procedure.yaml +44 -0
  156. package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +1 -1
  157. package/dist/agent-src/skills/existing-ui-audit/references/steps/00-inspect-stack-and-input.md +4 -0
  158. package/dist/agent-src/skills/existing-ui-audit/references/steps/01-enumerate-components.md +26 -0
  159. package/dist/agent-src/skills/existing-ui-audit/references/steps/01b-detect-component-taxonomy.md +7 -0
  160. package/dist/agent-src/skills/existing-ui-audit/references/steps/02-identify-design-system.md +12 -0
  161. package/dist/agent-src/skills/existing-ui-audit/references/steps/03-detect-design-tokens.md +35 -0
  162. package/dist/agent-src/skills/existing-ui-audit/references/steps/04-detect-shadcn-inventory.md +13 -0
  163. package/dist/agent-src/skills/existing-ui-audit/references/steps/04b-live-storybook-read.md +26 -0
  164. package/dist/agent-src/skills/existing-ui-audit/references/steps/05-list-reusable-patterns.md +14 -0
  165. package/dist/agent-src/skills/existing-ui-audit/references/steps/06-match-candidates.md +52 -0
  166. package/dist/agent-src/skills/existing-ui-audit/references/steps/07-greenfield-branch.md +29 -0
  167. package/dist/agent-src/skills/existing-ui-audit/references/steps/08-a11y-baseline.md +40 -0
  168. package/dist/agent-src/skills/existing-ui-audit/references/steps/09-validate-and-write.md +5 -0
  169. package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
  170. package/dist/agent-src/skills/fe-design/references/design-patterns.md +65 -4
  171. package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +1 -1
  172. package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
  173. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +6 -6
  174. package/dist/agent-src/skills/flux/SKILL.md +1 -1
  175. package/dist/agent-src/skills/form-handler/SKILL.md +15 -2
  176. package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
  177. package/dist/agent-src/skills/git-workflow/SKILL.md +2 -2
  178. package/dist/agent-src/skills/git-workflow/references/branch-update.md +7 -0
  179. package/dist/agent-src/skills/git-workflow/references/commit-subject.md +12 -0
  180. package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +10 -0
  181. package/dist/agent-src/skills/gtm-launch/SKILL.md +8 -1
  182. package/dist/agent-src/skills/html-deck/SKILL.md +7 -2
  183. package/dist/agent-src/skills/humanizer/SKILL.md +16 -3
  184. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +13 -1
  185. package/dist/agent-src/skills/humanizer/references/fixtures.md +8 -0
  186. package/dist/agent-src/skills/iconography/SKILL.md +4 -2
  187. package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
  188. package/dist/agent-src/skills/js-library-packaging/SKILL.md +5 -4
  189. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.mjs +197 -0
  190. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
  191. package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -2
  192. package/dist/agent-src/skills/launch-readiness/SKILL.md +18 -22
  193. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +5 -5
  194. package/dist/agent-src/skills/livewire/SKILL.md +1 -1
  195. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +18 -0
  196. package/dist/agent-src/skills/logo-generation/SKILL.md +21 -11
  197. package/dist/agent-src/skills/market-entry-analysis/SKILL.md +6 -1
  198. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  199. package/dist/agent-src/skills/memory-consolidation/SKILL.md +2 -2
  200. package/dist/agent-src/skills/messaging-architecture/SKILL.md +8 -1
  201. package/dist/agent-src/skills/motion-choreographer/SKILL.md +2 -2
  202. package/dist/agent-src/skills/playwright-testing/SKILL.md +2 -0
  203. package/dist/agent-src/skills/positioning-strategy/SKILL.md +10 -2
  204. package/dist/agent-src/skills/prediction-pool-optimizer/references/ev-fixtures.md +13 -0
  205. package/dist/agent-src/skills/prediction-pool-optimizer/references/odds-and-bonus.md +7 -0
  206. package/dist/agent-src/skills/project-analysis-core/SKILL.md +1 -1
  207. package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +1 -1
  208. package/dist/agent-src/skills/project-analyzer/SKILL.md +14 -75
  209. package/dist/agent-src/skills/project-analyzer/procedure.yaml +39 -0
  210. package/dist/agent-src/skills/project-analyzer/references/steps/01-project-overview.md +9 -0
  211. package/dist/agent-src/skills/project-analyzer/references/steps/02-architecture.md +7 -0
  212. package/dist/agent-src/skills/project-analyzer/references/steps/03-data-layer.md +6 -0
  213. package/dist/agent-src/skills/project-analyzer/references/steps/04-business-domains.md +7 -0
  214. package/dist/agent-src/skills/project-analyzer/references/steps/05-api-surface.md +6 -0
  215. package/dist/agent-src/skills/project-analyzer/references/steps/06-service-map.md +6 -0
  216. package/dist/agent-src/skills/project-analyzer/references/steps/07-module-inventory.md +6 -0
  217. package/dist/agent-src/skills/project-analyzer/references/steps/08-infrastructure-and-testing.md +5 -0
  218. package/dist/agent-src/skills/project-analyzer/references/steps/09-agent-docs-audit.md +6 -0
  219. package/dist/agent-src/skills/project-analyzer/references/steps/10-gap-analysis.md +6 -0
  220. package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +10 -0
  221. package/dist/agent-src/skills/quality-tools/references/php-tools.md +13 -0
  222. package/dist/agent-src/skills/quality-tools/references/python-tools.md +11 -0
  223. package/dist/agent-src/skills/react-native-setup/SKILL.md +7 -2
  224. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +5 -1
  225. package/dist/agent-src/skills/react-shadcn-ui/references/registry.md +13 -0
  226. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.mjs +315 -0
  227. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.ts +6 -6
  228. package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
  229. package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
  230. package/dist/agent-src/skills/release-comms/SKILL.md +2 -1
  231. package/dist/agent-src/skills/repomix-packer/SKILL.md +2 -2
  232. package/dist/agent-src/skills/requesting-code-review/SKILL.md +3 -3
  233. package/dist/agent-src/skills/roadmap-management/references/archival.md +3 -3
  234. package/dist/agent-src/skills/roadmap-management/references/authoring.md +9 -2
  235. package/dist/agent-src/skills/roadmap-management/references/dashboard.md +3 -3
  236. package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +3 -3
  237. package/dist/agent-src/skills/roadmap-writing/SKILL.md +4 -4
  238. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +1 -1
  239. package/dist/agent-src/skills/rule-writing/SKILL.md +1 -2
  240. package/dist/agent-src/skills/security/SKILL.md +41 -5
  241. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
  242. package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
  243. package/dist/agent-src/skills/skill-writing/SKILL.md +23 -8
  244. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +19 -1
  245. package/dist/agent-src/skills/source-discovery/SKILL.md +3 -3
  246. package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
  247. package/dist/agent-src/skills/standards-from-config/SKILL.md +2 -2
  248. package/dist/agent-src/skills/storybook-workshop/SKILL.md +5 -0
  249. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.mjs +99 -0
  250. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +13 -13
  251. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +4 -3
  252. package/dist/agent-src/skills/svg-authoring/SKILL.md +324 -0
  253. package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
  254. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +8 -3
  255. package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.mjs +482 -0
  256. package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
  257. package/dist/agent-src/skills/threat-modeling/SKILL.md +8 -1
  258. package/dist/agent-src/skills/threat-modeling/data/manifest.json +5 -2
  259. package/dist/agent-src/skills/threat-modeling/data/reasoning.csv +10 -10
  260. package/dist/agent-src/skills/threat-modeling/data/surfaces.csv +11 -10
  261. package/dist/agent-src/skills/threat-modeling/data/threats.csv +34 -20
  262. package/dist/agent-src/skills/type-design/SKILL.md +196 -0
  263. package/dist/agent-src/skills/type-design/references/font-spec.md +90 -0
  264. package/dist/agent-src/skills/type-design/references/gates.md +113 -0
  265. package/dist/agent-src/skills/type-design/references/toolchain.md +66 -0
  266. package/dist/agent-src/skills/typography-system/SKILL.md +21 -11
  267. package/dist/agent-src/skills/typography-system/references/worked-scales.md +85 -0
  268. package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
  269. package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
  270. package/dist/agent-src/skills/upstream-contribute/SKILL.md +120 -125
  271. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -0
  272. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +1 -1
  273. package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +71 -2
  274. package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
  275. package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +16 -14
  276. package/dist/agent-src/templates/AGENTS.md +1 -1
  277. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  278. package/dist/agent-src/templates/agents/proposal.example.md +1 -1
  279. package/dist/agent-src/templates/github-workflows/advisories-daily.yml +85 -0
  280. package/dist/agent-src/templates/roadmaps.md +39 -1
  281. package/dist/agent-src/templates/scripts/check_memory.ts +2 -2
  282. package/dist/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
  283. package/dist/agent-src/templates/scripts/work_engine/cli.ts +17 -0
  284. package/dist/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
  285. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
  286. package/dist/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
  287. package/dist/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
  288. package/dist/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
  289. package/dist/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
  290. package/dist/agent-src/templates/scripts/work_engine/state.ts +3 -0
  291. package/dist/cli/commands/uiRender.js +265 -13
  292. package/dist/cli/commands/uiRenderAsset.js +1316 -0
  293. package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
  294. package/dist/cli/commands/uiRenderAssetFonts.js +158 -0
  295. package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
  296. package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
  297. package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
  298. package/dist/cli/commands/uiRenderAssetTypes.js +133 -0
  299. package/dist/cli/initRouting.js +1 -1
  300. package/dist/cli/main.js +47 -1
  301. package/dist/cli/mcp/dispatch.js +31 -9
  302. package/dist/cli/python/knowledge_ingest.js +7 -39
  303. package/dist/cli/python/workspace_secrets.js +4 -177
  304. package/dist/cli/registry.js +5 -2
  305. package/dist/cli-delegate/archive_completed_roadmaps.js +3 -2
  306. package/dist/cli-delegate/check_update_banner.js +635 -266
  307. package/dist/cli-delegate/{chunk-AED2VQGM.js → chunk-2CX7NWRB.js} +233 -437
  308. package/dist/cli-delegate/{chunk-F3QDG2GT.js → chunk-2SFOOFJJ.js} +259 -159
  309. package/dist/cli-delegate/chunk-2Y5AMLMY.js +136 -0
  310. package/dist/cli-delegate/{chunk-OKJUIAPS.js → chunk-4E2W63DA.js} +1 -62
  311. package/dist/cli-delegate/{chunk-6SRJTYJS.js → chunk-4SHNERBL.js} +37 -16
  312. package/dist/cli-delegate/chunk-5VO3RTMV.js +208 -0
  313. package/dist/cli-delegate/chunk-6E2LDY4F.js +27 -0
  314. package/dist/cli-delegate/{chunk-XQTPXKFA.js → chunk-6ZD2QZMN.js} +8 -17
  315. package/dist/cli-delegate/{chunk-6V5FMA3P.js → chunk-7CEI2YPS.js} +1 -1
  316. package/dist/cli-delegate/{chunk-DMSZHXZS.js → chunk-7DRWULEQ.js} +80 -7
  317. package/dist/cli-delegate/chunk-7NXCZSDL.js +54 -0
  318. package/dist/cli-delegate/chunk-AX3U3UWJ.js +328 -0
  319. package/dist/cli-delegate/{chunk-WOKWX5PL.js → chunk-BKALSTBZ.js} +18 -3
  320. package/dist/cli-delegate/chunk-BMGUGSY6.js +103 -0
  321. package/dist/cli-delegate/chunk-BYV46VRM.js +3309 -0
  322. package/dist/cli-delegate/{chunk-5GPULQBE.js → chunk-CAL76ADI.js} +4215 -682
  323. package/dist/cli-delegate/chunk-DSY6LLCQ.js +127 -0
  324. package/dist/cli-delegate/chunk-E6XNBVE4.js +581 -0
  325. package/dist/cli-delegate/{chunk-ZUZKZYCN.js → chunk-ESUNQ5XR.js} +46 -10
  326. package/dist/cli-delegate/{chunk-G5VVIZRC.js → chunk-F7HLSW6P.js} +1 -1
  327. package/dist/cli-delegate/chunk-FIEEOH5C.js +133 -0
  328. package/dist/cli-delegate/chunk-FKYZOWVD.js +719 -0
  329. package/dist/cli-delegate/chunk-GOMILC3O.js +918 -0
  330. package/dist/cli-delegate/chunk-I4KJYVPB.js +69 -0
  331. package/dist/cli-delegate/{chunk-JQOM7TTM.js → chunk-IDAOTDPE.js} +1 -100
  332. package/dist/cli-delegate/chunk-IROAQ77A.js +137 -0
  333. package/dist/cli-delegate/chunk-J2SJZICO.js +698 -0
  334. package/dist/cli-delegate/{chunk-6YQC2HLF.js → chunk-JHMMWNJ2.js} +54 -40
  335. package/dist/cli-delegate/{chunk-WQWXGIWB.js → chunk-M6CRG5O6.js} +165 -15
  336. package/dist/cli-delegate/{chunk-PHD7OOLE.js → chunk-MQ2UDEGV.js} +14 -3
  337. package/dist/cli-delegate/chunk-NTM7G2V4.js +220 -0
  338. package/dist/cli-delegate/chunk-PV7S5DPJ.js +175 -0
  339. package/dist/cli-delegate/{chunk-F7DQWYR5.js → chunk-RAXQOETZ.js} +6 -2
  340. package/dist/cli-delegate/{chunk-T7XSJSUQ.js → chunk-SIOMDAKL.js} +980 -784
  341. package/dist/cli-delegate/{chunk-KR6EM23A.js → chunk-TULVDQ4L.js} +3 -48
  342. package/dist/cli-delegate/chunk-UUYEKXKR.js +20 -0
  343. package/dist/cli-delegate/{chunk-7XGD2OEU.js → chunk-UXWHY6CQ.js} +2 -1
  344. package/dist/cli-delegate/{chunk-PWX7CKMD.js → chunk-VC3ECUEK.js} +1 -1
  345. package/dist/cli-delegate/{chunk-KXXWJTDO.js → chunk-WMNYVIYX.js} +1 -1
  346. package/dist/cli-delegate/chunk-XCY5KKUC.js +181 -0
  347. package/dist/cli-delegate/{chunk-H76PHZBI.js → chunk-XLY5G3CM.js} +14 -19
  348. package/dist/cli-delegate/cmd_adr_effective.js +41 -2
  349. package/dist/cli-delegate/cmd_analyze_session.js +7 -7
  350. package/dist/cli-delegate/cmd_brand_status.js +1287 -10
  351. package/dist/cli-delegate/cmd_ci_settle.js +330 -0
  352. package/dist/cli-delegate/cmd_conformance.js +669 -822
  353. package/dist/cli-delegate/cmd_doctor.js +26 -16
  354. package/dist/cli-delegate/cmd_doctor_neighbours.js +10 -7
  355. package/dist/cli-delegate/cmd_explain.js +9 -24
  356. package/dist/cli-delegate/cmd_export.js +14 -11
  357. package/dist/cli-delegate/cmd_fleet.js +5 -3
  358. package/dist/cli-delegate/cmd_git_convention.js +8 -4
  359. package/dist/cli-delegate/cmd_handoff.js +79 -242
  360. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  361. package/dist/cli-delegate/cmd_memory_get.js +4 -2
  362. package/dist/cli-delegate/cmd_migrate.js +2 -2
  363. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  364. package/dist/cli-delegate/cmd_preflight.js +7 -5
  365. package/dist/cli-delegate/cmd_prune.js +16 -13
  366. package/dist/cli-delegate/cmd_route_audit.js +11 -8
  367. package/dist/cli-delegate/cmd_route_explain.js +649 -16
  368. package/dist/cli-delegate/cmd_session_recycle.js +15 -6
  369. package/dist/cli-delegate/cmd_settings_check.js +2 -2
  370. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  371. package/dist/cli-delegate/cmd_settings_migrate.js +14 -11
  372. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  373. package/dist/cli-delegate/cmd_sync.js +16 -13
  374. package/dist/cli-delegate/cmd_uninstall.js +185 -31
  375. package/dist/cli-delegate/cmd_update.js +67 -3
  376. package/dist/cli-delegate/cmd_upgrade.js +38 -7
  377. package/dist/cli-delegate/cmd_validate.js +16 -13
  378. package/dist/cli-delegate/cmd_versions.js +1 -1
  379. package/dist/cli-delegate/dashboard_mode.js +1 -1
  380. package/dist/cli-delegate/gate_execute.js +4 -3
  381. package/dist/cli-delegate/roadmap_age.js +22 -0
  382. package/dist/cli-delegate/roadmap_gates.js +4 -3
  383. package/dist/cli-delegate/update_roadmap_progress.js +3 -2
  384. package/dist/cli-delegate/upgrade_unattended-VVL6JLSX.js +541 -0
  385. package/dist/discovery/deprecation-report.md +1 -1
  386. package/dist/discovery/discovery-manifest.json +409 -201
  387. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  388. package/dist/discovery/discovery-manifest.summary.md +8 -8
  389. package/dist/discovery/dormancy-report.md +1 -1
  390. package/dist/discovery/orphan-report.md +1 -1
  391. package/dist/discovery/packs.json +36 -27
  392. package/dist/discovery/trust-report.md +3 -3
  393. package/dist/discovery/workspaces.json +25 -16
  394. package/dist/hooks/chat_history.chunk.cjs +6852 -0
  395. package/dist/hooks/chat_history.chunk.cjs.sha256 +1 -0
  396. package/dist/hooks/dispatch.js +17706 -18627
  397. package/dist/hooks/dispatch.sha256 +1 -1
  398. package/dist/hooks/egress_engine.chunk.cjs +915 -0
  399. package/dist/hooks/egress_engine.chunk.cjs.sha256 +1 -0
  400. package/dist/hooks/svg_rules.chunk.cjs +1858 -0
  401. package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
  402. package/dist/install/conflict.js +36 -6
  403. package/dist/install/conflictTracker.js +81 -7
  404. package/dist/install/detect.js +3 -3
  405. package/dist/install/hostPermissionsAdapter.js +106 -0
  406. package/dist/install/install.mjs +3117 -1949
  407. package/dist/install/installThinLayer.js +1 -1
  408. package/dist/install/manifestFiles.js +21 -0
  409. package/dist/install/noGoDenyRows.js +300 -0
  410. package/dist/install/noGoRules.js +368 -0
  411. package/dist/install/ownershipLedger.js +133 -0
  412. package/dist/install/plan.js +1 -1
  413. package/dist/install/preflight.js +39 -8
  414. package/dist/install/preserve.js +74 -12
  415. package/dist/install/recordedOwnership.js +88 -5
  416. package/dist/install/rule_scope.js +20 -3
  417. package/dist/install/stagedRuntime.js +455 -0
  418. package/dist/install/toolsArg.js +19 -0
  419. package/dist/install/userPin.js +47 -0
  420. package/dist/install/wizard-plan.js +26 -4
  421. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  422. package/dist/mcp/mcp-cloudflare-catalogue.json +3 -2
  423. package/dist/mcp/registry-manifest.json +6 -5
  424. package/dist/mcp/server.json +3 -3
  425. package/dist/mcp/server.mjs +9814 -5333
  426. package/dist/router.json +1 -1
  427. package/dist/scripts/_lib/agent_settings.js +7 -12
  428. package/dist/scripts/_lib/asset_render_record.js +219 -0
  429. package/dist/scripts/_lib/claude_builtin_names.js +9 -4
  430. package/dist/scripts/_lib/claude_settings_hooks.js +102 -34
  431. package/dist/scripts/_lib/egress_rules.js +766 -0
  432. package/dist/scripts/_lib/environment_detector.js +24 -33
  433. package/dist/scripts/_lib/global_deploy_inventory.js +146 -9
  434. package/dist/scripts/_lib/guidelines_lane.js +10 -1
  435. package/dist/scripts/_lib/identifier_redaction.js +24 -0
  436. package/dist/scripts/_lib/installed_layer.js +17 -0
  437. package/dist/scripts/_lib/installed_layer_normalise.js +72 -0
  438. package/dist/scripts/_lib/lean_projection_mode.js +34 -152
  439. package/dist/scripts/_lib/project_tree_form.js +118 -0
  440. package/dist/scripts/_lib/scan_scope.js +105 -0
  441. package/dist/scripts/_lib/scoped_projection.js +133 -3
  442. package/dist/scripts/_lib/settings_removed_keys.js +29 -0
  443. package/dist/scripts/_lib/settings_renamed_keys.js +17 -5
  444. package/dist/scripts/_lib/subagent_native_fields.js +35 -0
  445. package/dist/scripts/_lib/svg_dom.js +284 -0
  446. package/dist/scripts/_lib/svg_filled_counter.js +285 -0
  447. package/dist/scripts/_lib/svg_geometry.js +477 -0
  448. package/dist/scripts/_lib/svg_motion.js +179 -0
  449. package/dist/scripts/_lib/svg_rules.js +1339 -0
  450. package/dist/scripts/_lib/svg_urls.js +67 -0
  451. package/dist/scripts/_lib/ui_surface.js +19 -0
  452. package/dist/scripts/_lib/verification_command.js +364 -0
  453. package/dist/scripts/_lib/workspace_secrets.js +229 -0
  454. package/dist/scripts/ai_council/seat_policy.js +27 -0
  455. package/dist/scripts/ai_council/transport_resolver.js +9 -10
  456. package/dist/scripts/condense.js +25 -29
  457. package/dist/scripts/lint_svg_asset.js +324 -0
  458. package/dist/server/io/substituteTemplate.js +2 -2
  459. package/dist/server/io/yamlIO.js +2 -2
  460. package/dist/server/routes/install.js +5 -1
  461. package/dist/server/routes/settings.js +2 -2
  462. package/dist/server/routes/wizard.js +1 -1
  463. package/dist/server/schemas/settings.js +22 -16
  464. package/dist/server/serverInfo.js +1 -1
  465. package/dist/shared/brandTokenDocument.js +47 -0
  466. package/dist/shared/brandTokenPaths.js +43 -0
  467. package/dist/shared/settingsCarveOut.js +0 -7
  468. package/dist/shared/skillRanking.js +103 -5
  469. package/dist/shared/userMd/formAdapter.js +16 -0
  470. package/dist/shared/userMd/schema.js +17 -0
  471. package/dist/ui/assets/index-w70Ado09.js +23 -0
  472. package/dist/ui/index.html +1 -1
  473. package/docs/MIGRATION.md +89 -2
  474. package/docs/THIRD-PARTY-NOTICES.md +27 -0
  475. package/docs/contracts/settings-classes.md +27 -9
  476. package/docs/guidelines/agent-infra/api-cost-levers.md +4 -3
  477. package/docs/guidelines/agent-infra/model-recommendation.md +11 -5
  478. package/docs/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
  479. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
  480. package/docs/guidelines/design-antipatterns.md +6 -1
  481. package/docs/guidelines/design-asset-discipline.md +17 -0
  482. package/docs/guidelines/design-fidelity-routing.md +1 -0
  483. package/docs/guidelines/php/api-design.md +10 -1
  484. package/llms.txt +12 -10
  485. package/package.json +15 -5
  486. package/src/agent-src/scripts/dashboard_mode.ts +4 -1
  487. package/src/agent-src/scripts/roadmap_age.ts +175 -0
  488. package/src/agent-src/scripts/update_roadmap_progress.ts +10 -2
  489. package/src/agent-src/templates/AGENTS.md +1 -1
  490. package/src/agent-src/templates/scripts/check_memory.ts +2 -2
  491. package/src/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
  492. package/src/agent-src/templates/scripts/work_engine/cli.ts +17 -0
  493. package/src/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
  494. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
  495. package/src/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
  496. package/src/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
  497. package/src/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
  498. package/src/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
  499. package/src/agent-src/templates/scripts/work_engine/state.ts +3 -0
  500. package/src/config/agent-settings.template.yml +120 -57
  501. package/src/config/agents-paths.yml +13 -7
  502. package/src/config/ci-local-parity.yml +44 -0
  503. package/src/config/continuity-surface.json +51 -2
  504. package/src/config/depth-audit-samples.json +5 -0
  505. package/src/config/discovery/command-verbs.yml +1 -0
  506. package/src/config/dispatch-economy-metrics.json +1 -0
  507. package/src/config/egress-mutations/class-precedence-swapped.json +7 -0
  508. package/src/config/egress-mutations/credential-token-restores.json +7 -0
  509. package/src/config/egress-mutations/iban-checksum-disabled.json +7 -0
  510. package/src/config/egress-mutations/raw-value-in-the-count-record.json +7 -0
  511. package/src/config/evaluator-budgets.json +4 -4
  512. package/src/config/gate-coverage.yml +149 -3
  513. package/src/config/gate-reachability-exemptions.json +3 -5
  514. package/src/config/gate-violation-baselines.json +29 -25
  515. package/src/config/gitignore-block.txt +6 -3
  516. package/src/config/hook-bundle-budget.json +34 -3
  517. package/src/config/hook-carrier-probes.json +30 -0
  518. package/src/config/hook-latency-budget.json +4 -2
  519. package/src/config/host-injection-effect.json +8 -1
  520. package/src/config/host-skill-frontmatter-keys.json +56 -0
  521. package/src/config/layer-form-brakes.json +4 -0
  522. package/src/config/layer-form-comparison-corpus.json +42 -0
  523. package/src/config/loop-surfaces.yaml +28 -47
  524. package/src/config/memory-twin-verdicts.yml +9 -1
  525. package/src/config/metric-registry.yml +40 -3
  526. package/src/config/pack-size-budget.json +15 -0
  527. package/src/config/procedure-core-budget.json +21 -0
  528. package/src/config/profiles/minimal.ini +1 -1
  529. package/src/config/project-tree-form.json +24 -0
  530. package/src/config/reach-channels.yml +3 -3
  531. package/src/config/reach-prescriptions-intake.yml +1 -1
  532. package/src/config/roadmap-step-size-baseline.json +118 -0
  533. package/src/config/routing-coverage-seed.json +100 -2
  534. package/src/config/skill-body-budget.json +686 -0
  535. package/src/config/skill-fork-pilot.json +17 -0
  536. package/src/config/skill-lifecycle-probes-codex.json +57 -0
  537. package/src/config/skill-lifecycle-probes.json +57 -0
  538. package/src/config/skill-output-shape.json +316 -0
  539. package/src/config/step-depth-table.json +58 -0
  540. package/src/config/turnaround-budget.json +90 -0
  541. package/src/install/conflict.ts +38 -6
  542. package/src/install/conflictTracker.ts +126 -8
  543. package/src/install/detect.ts +3 -3
  544. package/src/install/hostPermissionsAdapter.ts +136 -0
  545. package/src/install/installThinLayer.ts +6 -1
  546. package/src/install/manifestFiles.ts +24 -0
  547. package/src/install/noGoDenyRows.ts +368 -0
  548. package/src/install/noGoRules.ts +438 -0
  549. package/src/install/ownershipLedger.ts +180 -0
  550. package/src/install/plan.ts +1 -1
  551. package/src/install/preflight.ts +42 -10
  552. package/src/install/preserve.ts +94 -12
  553. package/src/install/recordedOwnership.ts +121 -3
  554. package/src/install/rule_scope.ts +20 -3
  555. package/src/install/stagedRuntime.ts +528 -0
  556. package/src/install/toolsArg.ts +16 -0
  557. package/src/install/types.ts +23 -2
  558. package/src/install/userPin.ts +54 -0
  559. package/src/install/wizard-plan.ts +25 -4
  560. package/src/scripts/_cli/_doctor_emit.ts +24 -0
  561. package/src/scripts/_cli/cmd_brand_status.ts +223 -12
  562. package/src/scripts/_cli/cmd_ci_settle.ts +32 -0
  563. package/src/scripts/_cli/cmd_doctor.ts +23 -44
  564. package/src/scripts/_cli/cmd_route_explain.ts +176 -2
  565. package/src/scripts/_cli/cmd_uninstall.ts +270 -26
  566. package/src/scripts/_cli/cmd_update.ts +34 -1
  567. package/src/scripts/_cli/cmd_upgrade.ts +38 -2
  568. package/src/scripts/_cli/detection_report.ts +7 -0
  569. package/src/scripts/_cli/doctor_execution.ts +1 -2
  570. package/src/scripts/_cli/doctor_install_mode.ts +39 -0
  571. package/src/scripts/_cli/doctor_network_posture.ts +3 -3
  572. package/src/scripts/_cli/doctor_ownership_ledger.ts +126 -0
  573. package/src/scripts/_cli/doctor_update_verdict.ts +104 -0
  574. package/src/scripts/_cli/explain_last/scrubber.ts +9 -21
  575. package/src/scripts/_cli/upgrade_unattended.ts +548 -0
  576. package/src/scripts/_dispatch.bash +42 -9
  577. package/src/scripts/_lib/activation_ladder.ts +1 -1
  578. package/src/scripts/_lib/advisory_inventory.ts +405 -0
  579. package/src/scripts/_lib/advisory_notice.ts +270 -0
  580. package/src/scripts/_lib/advisory_sources.ts +752 -0
  581. package/src/scripts/_lib/advisory_verdicts.ts +363 -0
  582. package/src/scripts/_lib/agent_artifact_location.ts +177 -0
  583. package/src/scripts/_lib/agent_settings.ts +7 -12
  584. package/src/scripts/_lib/arrival_record.ts +217 -0
  585. package/src/scripts/_lib/asset_render_record.ts +247 -0
  586. package/src/scripts/_lib/billing_grant.ts +4 -2
  587. package/src/scripts/_lib/brand_voice_slot.ts +258 -0
  588. package/src/scripts/_lib/canary_status.ts +24 -0
  589. package/src/scripts/_lib/cc_transcript.ts +276 -0
  590. package/src/scripts/_lib/changelog_eras.ts +83 -0
  591. package/src/scripts/_lib/claim_phrases.ts +71 -0
  592. package/src/scripts/_lib/classify_update.ts +171 -0
  593. package/src/scripts/_lib/claude_builtin_names.ts +9 -4
  594. package/src/scripts/_lib/claude_hook_scope.ts +195 -0
  595. package/src/scripts/_lib/claude_settings_hooks.ts +118 -34
  596. package/src/scripts/_lib/codex_resident_set.ts +460 -0
  597. package/src/scripts/_lib/codex_skill_finder.ts +225 -0
  598. package/src/scripts/_lib/confusables.ts +19 -0
  599. package/src/scripts/_lib/consumer_impact.ts +199 -0
  600. package/src/scripts/_lib/content_class.ts +127 -0
  601. package/src/scripts/_lib/counted_probe.ts +68 -1
  602. package/src/scripts/_lib/credential_deny_rows.ts +151 -0
  603. package/src/scripts/_lib/credential_files.ts +367 -0
  604. package/src/scripts/_lib/delivery_arm_experiment.ts +2 -2
  605. package/src/scripts/_lib/depth_flip.ts +141 -0
  606. package/src/scripts/_lib/design_lock.ts +117 -0
  607. package/src/scripts/_lib/design_sync_ledger.ts +142 -0
  608. package/src/scripts/_lib/design_sync_plan.ts +177 -0
  609. package/src/scripts/_lib/design_sync_reconcile.ts +159 -0
  610. package/src/scripts/_lib/design_sync_verify.ts +99 -0
  611. package/src/scripts/_lib/design_system_claude_design.ts +323 -0
  612. package/src/scripts/_lib/design_system_import.ts +84 -6
  613. package/src/scripts/_lib/dispatch_import_closure.ts +42 -11
  614. package/src/scripts/_lib/egress_credential_env.ts +35 -0
  615. package/src/scripts/_lib/egress_engine.ts +22 -0
  616. package/src/scripts/_lib/egress_known_values.ts +223 -0
  617. package/src/scripts/_lib/egress_normalize.ts +67 -0
  618. package/src/scripts/_lib/egress_prefixes.ts +42 -0
  619. package/src/scripts/_lib/egress_rules.ts +896 -0
  620. package/src/scripts/_lib/egress_rules_linearity.ts +56 -0
  621. package/src/scripts/_lib/egress_sender_scan.ts +290 -0
  622. package/src/scripts/_lib/egress_session_table.ts +510 -0
  623. package/src/scripts/_lib/egress_text.ts +63 -0
  624. package/src/scripts/_lib/egress_token.ts +252 -0
  625. package/src/scripts/_lib/empty_cycles.ts +1 -1
  626. package/src/scripts/_lib/environment_detector.ts +45 -30
  627. package/src/scripts/_lib/exemption_shape.ts +75 -1
  628. package/src/scripts/_lib/floor_posture.ts +185 -0
  629. package/src/scripts/_lib/forge_protection.ts +140 -2
  630. package/src/scripts/_lib/global_deploy_inventory.ts +159 -6
  631. package/src/scripts/_lib/guidelines_lane.ts +12 -1
  632. package/src/scripts/_lib/hand_kinds.ts +65 -0
  633. package/src/scripts/_lib/headless_invocation.ts +3 -3
  634. package/src/scripts/_lib/host_capability.ts +34 -2
  635. package/src/scripts/_lib/host_env_write.ts +39 -18
  636. package/src/scripts/_lib/host_listing_model.ts +14 -7
  637. package/src/scripts/_lib/identifier_redaction.ts +26 -0
  638. package/src/scripts/_lib/impact_bump.ts +70 -0
  639. package/src/scripts/_lib/install_reach_checks.ts +53 -1
  640. package/src/scripts/_lib/installed_layer.ts +31 -0
  641. package/src/scripts/_lib/installed_layer_normalise.ts +75 -0
  642. package/src/scripts/_lib/instructions_loaded_classify.ts +75 -0
  643. package/src/scripts/_lib/instructions_loaded_event.ts +53 -0
  644. package/src/scripts/_lib/knowledge_global_redaction.ts +2 -2
  645. package/src/scripts/_lib/layer_form_corpus.ts +165 -0
  646. package/src/scripts/_lib/layer_form_decision.ts +248 -0
  647. package/src/scripts/_lib/layer_form_evidence.ts +112 -0
  648. package/src/scripts/_lib/lean_projection_mode.ts +32 -161
  649. package/src/scripts/_lib/llm_proposer_transport.ts +1 -0
  650. package/src/scripts/_lib/loop_guards.ts +8 -120
  651. package/src/scripts/_lib/major_surface.ts +207 -0
  652. package/src/scripts/_lib/mcp_bridge.ts +30 -69
  653. package/src/scripts/_lib/merge_clearance_record.ts +384 -0
  654. package/src/scripts/_lib/neighbour_census.ts +18 -1
  655. package/src/scripts/_lib/orchestration_record.ts +61 -0
  656. package/src/scripts/_lib/outcome_vocabularies.ts +15 -23
  657. package/src/scripts/_lib/pin_advice.ts +49 -0
  658. package/src/scripts/_lib/platform_anchor.ts +222 -0
  659. package/src/scripts/_lib/procedure_checks.ts +5 -0
  660. package/src/scripts/_lib/project_tree_form.ts +134 -0
  661. package/src/scripts/_lib/projection_key_migration.ts +122 -0
  662. package/src/scripts/_lib/prompt_shape.ts +13 -2
  663. package/src/scripts/_lib/provenance_verify.ts +272 -0
  664. package/src/scripts/_lib/quota_parked.ts +27 -1
  665. package/src/scripts/_lib/ratification_artifact.ts +64 -1
  666. package/src/scripts/_lib/ratification_subject.ts +508 -46
  667. package/src/scripts/_lib/release_findings_ingest.ts +52 -5
  668. package/src/scripts/_lib/release_highlights.ts +72 -2
  669. package/src/scripts/_lib/release_settings_surface.ts +392 -0
  670. package/src/scripts/_lib/review_round.ts +134 -0
  671. package/src/scripts/_lib/roadmap_checkboxes.ts +1 -1
  672. package/src/scripts/_lib/roadmap_slug_lock.ts +254 -0
  673. package/src/scripts/_lib/roadmap_step_size.ts +75 -0
  674. package/src/scripts/_lib/run_checkpoint.ts +60 -3
  675. package/src/scripts/_lib/runtime_wiring_checks.ts +15 -1
  676. package/src/scripts/_lib/scope_guard.sh +64 -5
  677. package/src/scripts/_lib/scoped_projection.ts +136 -3
  678. package/src/scripts/_lib/secret_detector.ts +24 -103
  679. package/src/scripts/_lib/security_fix.ts +429 -0
  680. package/src/scripts/_lib/security_fix_context.ts +133 -0
  681. package/src/scripts/_lib/self_repair.ts +69 -39
  682. package/src/scripts/_lib/self_repair_outgoing.ts +209 -0
  683. package/src/scripts/_lib/self_repair_payload.ts +86 -0
  684. package/src/scripts/_lib/session_eol.ts +3 -0
  685. package/src/scripts/_lib/session_pr_watch.ts +207 -0
  686. package/src/scripts/_lib/session_register.ts +51 -1
  687. package/src/scripts/_lib/session_tag.ts +51 -0
  688. package/src/scripts/_lib/settings_removed_keys.ts +30 -0
  689. package/src/scripts/_lib/settings_renamed_keys.ts +19 -5
  690. package/src/scripts/_lib/skill_catalogue.ts +66 -25
  691. package/src/scripts/_lib/skill_fork_pilot.ts +121 -0
  692. package/src/scripts/_lib/skill_leases.ts +203 -0
  693. package/src/scripts/_lib/skill_listing_overrides.ts +294 -0
  694. package/src/scripts/_lib/skill_materialisation.ts +388 -0
  695. package/src/scripts/_lib/skill_materialisation_gate.ts +210 -0
  696. package/src/scripts/_lib/skill_materialisation_lock.ts +149 -0
  697. package/src/scripts/_lib/skill_materialisation_triggers.ts +96 -0
  698. package/src/scripts/_lib/skill_origin.ts +21 -1
  699. package/src/scripts/_lib/skill_reach.ts +342 -0
  700. package/src/scripts/_lib/source_shape.ts +7 -2
  701. package/src/scripts/_lib/sqlite_guard.ts +1 -1
  702. package/src/scripts/_lib/step_anatomy.ts +330 -0
  703. package/src/scripts/_lib/subagent_capsule.ts +8 -2
  704. package/src/scripts/_lib/subagent_native_fields.ts +30 -0
  705. package/src/scripts/_lib/subagent_spawn.ts +36 -0
  706. package/src/scripts/_lib/subagent_steering.ts +367 -0
  707. package/src/scripts/_lib/svg_dom.ts +318 -0
  708. package/src/scripts/_lib/svg_filled_counter.ts +287 -0
  709. package/src/scripts/_lib/svg_geometry.ts +480 -0
  710. package/src/scripts/_lib/svg_motion.ts +208 -0
  711. package/src/scripts/_lib/svg_rules.ts +1455 -0
  712. package/src/scripts/_lib/svg_urls.ts +72 -0
  713. package/src/scripts/_lib/test_delta.ts +89 -6
  714. package/src/scripts/_lib/tier_downshift_verdict.ts +222 -0
  715. package/src/scripts/_lib/tool_result_census.ts +62 -0
  716. package/src/scripts/_lib/trigger_routers.ts +1 -0
  717. package/src/scripts/_lib/turnaround_throughput.ts +378 -0
  718. package/src/scripts/_lib/ui_surface.ts +22 -0
  719. package/src/scripts/_lib/unattended_gates.ts +100 -0
  720. package/src/scripts/_lib/undeployed_fixes.ts +34 -0
  721. package/src/scripts/_lib/update_check.ts +143 -12
  722. package/src/scripts/_lib/update_invite.ts +116 -0
  723. package/src/scripts/_lib/update_notice.ts +259 -0
  724. package/src/scripts/_lib/verification_command.ts +59 -0
  725. package/src/scripts/_lib/verify_clause.ts +31 -19
  726. package/src/scripts/_lib/version_order.ts +146 -0
  727. package/src/scripts/_lib/worker_reuse.ts +191 -0
  728. package/src/scripts/_lib/workspace_secrets.ts +273 -0
  729. package/src/scripts/_lib/worktree_git.ts +67 -0
  730. package/src/scripts/_lib/worktree_ignored.ts +116 -0
  731. package/src/scripts/adoption_status.ts +330 -3
  732. package/src/scripts/adr_cite_check.ts +93 -0
  733. package/src/scripts/advisories.ts +803 -0
  734. package/src/scripts/ai-image/adapters/flux.sh +1 -0
  735. package/src/scripts/ai-image/adapters/gemini-image.sh +1 -0
  736. package/src/scripts/ai-image/adapters/ideogram.sh +1 -0
  737. package/src/scripts/ai-image/adapters/recraft.sh +1 -0
  738. package/src/scripts/ai-video/adapters/comfyui.sh +1 -0
  739. package/src/scripts/ai-video/adapters/fal.sh +1 -0
  740. package/src/scripts/ai-video/adapters/gemini-veo.sh +1 -0
  741. package/src/scripts/ai-video/adapters/higgsfield.sh +1 -0
  742. package/src/scripts/ai-video/adapters/kling.sh +1 -0
  743. package/src/scripts/ai-video/adapters/musetalk.sh +1 -0
  744. package/src/scripts/ai-video/adapters/openai-images.sh +1 -0
  745. package/src/scripts/ai-video/adapters/replicate.sh +1 -0
  746. package/src/scripts/ai-video/adapters/sora.sh +1 -0
  747. package/src/scripts/ai-video/adapters/syncso.sh +1 -0
  748. package/src/scripts/ai-video/stitch.sh +115 -2
  749. package/src/scripts/ai_council/airgap.ts +1 -0
  750. package/src/scripts/ai_council/api_transport.ts +27 -4
  751. package/src/scripts/ai_council/budget_guard.ts +300 -11
  752. package/src/scripts/ai_council/bundler.ts +20 -29
  753. package/src/scripts/ai_council/chairman.ts +17 -2
  754. package/src/scripts/ai_council/cli_agency_bounds.ts +158 -0
  755. package/src/scripts/ai_council/cli_launch_env.ts +54 -0
  756. package/src/scripts/ai_council/cli_least_agency_canary.ts +18 -2
  757. package/src/scripts/ai_council/clients.ts +55 -73
  758. package/src/scripts/ai_council/config.ts +16 -22
  759. package/src/scripts/ai_council/council_egress.ts +167 -0
  760. package/src/scripts/ai_council/exposure_ledger.ts +117 -0
  761. package/src/scripts/ai_council/free_hand_shadow.ts +276 -0
  762. package/src/scripts/ai_council/free_route.ts +216 -0
  763. package/src/scripts/ai_council/free_route_catalog.ts +173 -0
  764. package/src/scripts/ai_council/free_route_client.ts +95 -0
  765. package/src/scripts/ai_council/free_rung.ts +61 -0
  766. package/src/scripts/ai_council/hand_payload.ts +230 -0
  767. package/src/scripts/ai_council/hand_schemas.ts +123 -0
  768. package/src/scripts/ai_council/jury_aggregate.ts +155 -1
  769. package/src/scripts/ai_council/kind_flip.ts +221 -0
  770. package/src/scripts/ai_council/kind_flip_state.ts +19 -0
  771. package/src/scripts/ai_council/learn_low_impact_preview.ts +50 -22
  772. package/src/scripts/ai_council/modification_review.ts +98 -5
  773. package/src/scripts/ai_council/necessity.ts +7 -0
  774. package/src/scripts/ai_council/orchestrator.ts +16 -16
  775. package/src/scripts/ai_council/pricing.ts +10 -0
  776. package/src/scripts/ai_council/redact_low_impact_entry.ts +5 -2
  777. package/src/scripts/ai_council/response_render.ts +27 -4
  778. package/src/scripts/ai_council/round_reservations.ts +119 -0
  779. package/src/scripts/ai_council/route_chooser.ts +161 -0
  780. package/src/scripts/ai_council/route_liveness.ts +152 -0
  781. package/src/scripts/ai_council/route_member.ts +52 -0
  782. package/src/scripts/ai_council/seat_policy.ts +40 -0
  783. package/src/scripts/ai_council/seat_resume.ts +40 -0
  784. package/src/scripts/ai_council/shadow_dispatch.ts +13 -3
  785. package/src/scripts/ai_council/spend_gate.ts +18 -2
  786. package/src/scripts/ai_council/status_surface.ts +37 -0
  787. package/src/scripts/ai_council/transport_resolver.ts +15 -18
  788. package/src/scripts/analysis_analysts.ts +226 -0
  789. package/src/scripts/analysis_anchors.ts +140 -0
  790. package/src/scripts/analysis_and_optimize.ts +44 -0
  791. package/src/scripts/analysis_emit.ts +150 -0
  792. package/src/scripts/analysis_exchange.ts +186 -0
  793. package/src/scripts/analysis_gate.ts +158 -0
  794. package/src/scripts/analysis_inbox_final.ts +173 -0
  795. package/src/scripts/analysis_ledger.ts +119 -0
  796. package/src/scripts/analysis_pr_optimize.ts +219 -0
  797. package/src/scripts/analysis_pr_review.ts +240 -0
  798. package/src/scripts/analysis_pr_target.ts +121 -0
  799. package/src/scripts/analysis_prompts.ts +130 -0
  800. package/src/scripts/analysis_publish.ts +358 -0
  801. package/src/scripts/analysis_questions.ts +78 -0
  802. package/src/scripts/analysis_run.ts +248 -0
  803. package/src/scripts/analysis_run_record.ts +210 -0
  804. package/src/scripts/analysis_target.ts +343 -0
  805. package/src/scripts/analysis_validate.ts +161 -0
  806. package/src/scripts/anchor_eval_falsify.ts +1 -1
  807. package/src/scripts/arrival_report.ts +115 -0
  808. package/src/scripts/ask_transport.ts +284 -35
  809. package/src/scripts/backfill_model_tier.ts +4 -5
  810. package/src/scripts/before_complete_hook.ts +48 -2
  811. package/src/scripts/bench_hook_latency.ts +3 -3
  812. package/src/scripts/bench_procedure_cursor.ts +440 -0
  813. package/src/scripts/bootstrap.sh +3 -3
  814. package/src/scripts/build_exit_code_register.ts +440 -0
  815. package/src/scripts/build_proof.ts +23 -1
  816. package/src/scripts/cache_realization_report.ts +155 -14
  817. package/src/scripts/canary_liveness.ts +117 -0
  818. package/src/scripts/chat_history.ts +12 -15
  819. package/src/scripts/check_account_surface.ts +318 -0
  820. package/src/scripts/check_agent_artifact_location.ts +17 -160
  821. package/src/scripts/check_bundle_path_leakage.ts +6 -0
  822. package/src/scripts/check_ci_local_parity.ts +21 -13
  823. package/src/scripts/check_claims.ts +77 -2
  824. package/src/scripts/check_completion_review.ts +34 -1
  825. package/src/scripts/check_concern_admissions.ts +41 -5
  826. package/src/scripts/check_consumer_scope_flip.ts +1 -1
  827. package/src/scripts/check_context_paths.ts +2 -0
  828. package/src/scripts/check_council_layout.ts +9 -0
  829. package/src/scripts/check_credential_spelling.ts +267 -0
  830. package/src/scripts/check_egress_mutations.ts +239 -0
  831. package/src/scripts/check_enforcement_coverage.ts +16 -3
  832. package/src/scripts/check_estate_count.ts +16 -1
  833. package/src/scripts/check_finding_dispositions.ts +147 -0
  834. package/src/scripts/check_gate_coverage.ts +123 -21
  835. package/src/scripts/check_gate_reachability.ts +16 -2
  836. package/src/scripts/check_generator_sync.ts +46 -0
  837. package/src/scripts/check_hook_bundle_composition.ts +139 -1
  838. package/src/scripts/check_host_docs_digest.ts +142 -5
  839. package/src/scripts/check_kernel_edit_ratified.ts +301 -76
  840. package/src/scripts/check_kernel_rule_bundle.ts +14 -10
  841. package/src/scripts/check_knowledge_cards.ts +83 -3
  842. package/src/scripts/check_memory.ts +13 -3
  843. package/src/scripts/check_pack_size.ts +1 -1
  844. package/src/scripts/check_permission_deny_syntax.ts +247 -0
  845. package/src/scripts/check_platform_anchor.ts +243 -0
  846. package/src/scripts/check_proposal.ts +183 -1
  847. package/src/scripts/check_reach_channels.ts +5 -3
  848. package/src/scripts/check_references.ts +5 -2
  849. package/src/scripts/check_release_manifest_content.ts +33 -0
  850. package/src/scripts/check_release_pr_shape.ts +5 -0
  851. package/src/scripts/check_rule_invariants.ts +9 -1
  852. package/src/scripts/check_skill_body_budget.ts +343 -0
  853. package/src/scripts/check_skill_requires.ts +137 -1
  854. package/src/scripts/check_step_receipts.ts +246 -0
  855. package/src/scripts/check_structural_breaking.ts +7 -1
  856. package/src/scripts/check_suppression_hygiene.ts +8 -0
  857. package/src/scripts/check_test_weakening.ts +14 -0
  858. package/src/scripts/check_token_quality_golden.ts +5 -1
  859. package/src/scripts/check_update_banner.ts +50 -3
  860. package/src/scripts/check_verify_expectation_delta.ts +2 -1
  861. package/src/scripts/check_voice_lexicon.ts +531 -0
  862. package/src/scripts/ci_os_attribution.ts +327 -0
  863. package/src/scripts/ci_platform_scope.ts +69 -0
  864. package/src/scripts/ci_settle.ts +4 -1
  865. package/src/scripts/ci_status.ts +0 -1
  866. package/src/scripts/ci_time_to_green.ts +748 -0
  867. package/src/scripts/classify_merge_risk.ts +407 -19
  868. package/src/scripts/code_graph/sqlite_store.ts +1 -1
  869. package/src/scripts/compile_trigger_evals.ts +353 -0
  870. package/src/scripts/condense.ts +25 -31
  871. package/src/scripts/consumer_matrix.ts +61 -3
  872. package/src/scripts/council_availability_hook.ts +12 -4
  873. package/src/scripts/council_cli.ts +48 -38
  874. package/src/scripts/cross_repo_retrieve.ts +9 -72
  875. package/src/scripts/design_lock.ts +106 -0
  876. package/src/scripts/design_slop_rules.ts +30 -0
  877. package/src/scripts/design_sync.ts +264 -0
  878. package/src/scripts/design_system_import.ts +30 -13
  879. package/src/scripts/dispatch_economy_report.ts +46 -1
  880. package/src/scripts/dispatch_r2_reviewer.ts +41 -5
  881. package/src/scripts/egress_canary.ts +166 -0
  882. package/src/scripts/egress_sender_census.ts +101 -0
  883. package/src/scripts/external_sources_denylist.json +94 -12
  884. package/src/scripts/generate_catalog.ts +6 -2
  885. package/src/scripts/generate_owned_digest.ts +163 -0
  886. package/src/scripts/generate_reference_toc.ts +143 -0
  887. package/src/scripts/generate_subagent_floor.ts +11 -1
  888. package/src/scripts/handoff_context_hook.ts +34 -0
  889. package/src/scripts/hook_carrier_census.ts +263 -0
  890. package/src/scripts/hook_chunks.d.mts +12 -0
  891. package/src/scripts/hook_chunks.mjs +114 -0
  892. package/src/scripts/hook_manifest.json +1 -1
  893. package/src/scripts/hook_manifest.yaml +65 -42
  894. package/src/scripts/hooks/block_config_weakening.ts +127 -3
  895. package/src/scripts/hooks/block_credential_reads.ts +165 -0
  896. package/src/scripts/hooks/block_no_verify.ts +47 -23
  897. package/src/scripts/hooks/block_speaking_inbox_dir.ts +54 -8
  898. package/src/scripts/hooks/category_a.ts +202 -25
  899. package/src/scripts/hooks/concern_failure_policy.ts +6 -6
  900. package/src/scripts/hooks/concern_registry.ts +31 -6
  901. package/src/scripts/hooks/concern_registry_types.ts +11 -0
  902. package/src/scripts/hooks/delegation_nudge_hook.ts +105 -15
  903. package/src/scripts/hooks/design_pass_hook.ts +199 -13
  904. package/src/scripts/hooks/dispatch_hook.ts +13 -12
  905. package/src/scripts/hooks/egress_engine_loader.ts +125 -0
  906. package/src/scripts/hooks/egress_stage.ts +440 -0
  907. package/src/scripts/hooks/hook_stdin.ts +29 -4
  908. package/src/scripts/hooks/host_docs_pages.ts +194 -0
  909. package/src/scripts/hooks/host_docs_pages.yaml +75 -0
  910. package/src/scripts/hooks/host_lowering.json +1 -1
  911. package/src/scripts/hooks/host_lowering.yaml +22 -21
  912. package/src/scripts/hooks/host_rate_marker_hook.ts +73 -0
  913. package/src/scripts/hooks/instructions_observer_hook.ts +170 -0
  914. package/src/scripts/hooks/interruption_ledger_hook.ts +1 -1
  915. package/src/scripts/hooks/lazy_concern.ts +148 -0
  916. package/src/scripts/hooks/orchestration_record_hook.ts +80 -2
  917. package/src/scripts/hooks/payload_stub.ts +16 -6
  918. package/src/scripts/hooks/permission_gate.ts +7 -7
  919. package/src/scripts/hooks/push_settle_hook.ts +32 -3
  920. package/src/scripts/hooks/replay_hook.ts +43 -0
  921. package/src/scripts/hooks/reread_guard_hook.ts +87 -10
  922. package/src/scripts/hooks/rtk_wrap_hook.ts +4 -3
  923. package/src/scripts/hooks/rule_inject_hook.ts +8 -1
  924. package/src/scripts/hooks/session_eol_hook.ts +48 -1
  925. package/src/scripts/hooks/source_first_gate_hook.ts +6 -8
  926. package/src/scripts/hooks/spawn_guard_shadow_hook.ts +203 -10
  927. package/src/scripts/hooks/state_io.ts +2 -2
  928. package/src/scripts/hooks/svg_obligation.ts +553 -0
  929. package/src/scripts/hooks/svg_rules_loader.ts +133 -0
  930. package/src/scripts/hooks/tool_result_bytes_hook.ts +14 -5
  931. package/src/scripts/hooks/turn_end_gate_hook.ts +5 -3
  932. package/src/scripts/hooks/ui_route_nudge_hook.ts +2 -12
  933. package/src/scripts/hooks_doctor.ts +31 -0
  934. package/src/scripts/hooks_status.ts +58 -3
  935. package/src/scripts/inbox_source_census.ts +74 -13
  936. package/src/scripts/install +25 -3
  937. package/src/scripts/install.ts +60 -91
  938. package/src/scripts/interruption_report.ts +11 -1
  939. package/src/scripts/layer_baseline_report.ts +267 -0
  940. package/src/scripts/learning_sidecar.ts +1 -1
  941. package/src/scripts/lint_agents_layout.ts +3 -0
  942. package/src/scripts/lint_blocker_citations.ts +104 -0
  943. package/src/scripts/lint_breaking_changes_index.ts +40 -7
  944. package/src/scripts/lint_consolidation_lineage.ts +150 -19
  945. package/src/scripts/lint_consumer_internal_refs.ts +90 -42
  946. package/src/scripts/lint_context_spine_usage.ts +21 -0
  947. package/src/scripts/lint_design_antipattern_parity.ts +39 -7
  948. package/src/scripts/lint_design_quality.ts +60 -12
  949. package/src/scripts/lint_evidence_artifacts.ts +31 -0
  950. package/src/scripts/lint_example_fences.ts +11 -2
  951. package/src/scripts/lint_ghostwriter_source.ts +42 -10
  952. package/src/scripts/lint_hook_manifest.ts +94 -0
  953. package/src/scripts/lint_marketplace_install_completeness.ts +4 -0
  954. package/src/scripts/lint_mcp_config_security.ts +9 -11
  955. package/src/scripts/lint_motion_authority_drift.ts +27 -0
  956. package/src/scripts/lint_plan_risk_register.ts +28 -1
  957. package/src/scripts/lint_positioning.ts +4 -4
  958. package/src/scripts/lint_provenance.ts +1 -0
  959. package/src/scripts/lint_roadmap_blockers.ts +65 -4
  960. package/src/scripts/lint_roadmap_complexity.ts +98 -0
  961. package/src/scripts/lint_skill_link_reach.ts +251 -9
  962. package/src/scripts/lint_skill_procedures.ts +252 -0
  963. package/src/scripts/lint_skill_scripts_readonly.ts +12 -1
  964. package/src/scripts/lint_subagent_determinism.ts +14 -1
  965. package/src/scripts/lint_svg_asset.ts +365 -0
  966. package/src/scripts/lint_ticked_unmet_criteria.ts +300 -21
  967. package/src/scripts/mcp_registry_submit.sh +2 -2
  968. package/src/scripts/mcp_server/consumer_tool_catalog.json +4 -4
  969. package/src/scripts/mcp_server/suggest_skill.ts +89 -4
  970. package/src/scripts/mcp_server/tools.ts +2 -33
  971. package/src/scripts/measure_skill_ranker_baseline.ts +203 -5
  972. package/src/scripts/measure_turn_end_gate.ts +61 -1
  973. package/src/scripts/merge_clearance.ts +225 -0
  974. package/src/scripts/migrate_command_suggestions.ts +1 -1
  975. package/src/scripts/network_sources.ts +236 -0
  976. package/src/scripts/no_go_deny_rows.ts +225 -0
  977. package/src/scripts/orchestration_record.ts +15 -2
  978. package/src/scripts/plan_test_shards.ts +103 -0
  979. package/src/scripts/pr_url_reminder_hook.ts +10 -0
  980. package/src/scripts/print_required_checks.ts +5 -5
  981. package/src/scripts/probe_depth_shadow.ts +406 -0
  982. package/src/scripts/probe_turnaround.ts +342 -10
  983. package/src/scripts/ratification_subject.ts +176 -0
  984. package/src/scripts/rdp_gate_classify.ts +1 -0
  985. package/src/scripts/rdp_quality_eval.ts +1 -0
  986. package/src/scripts/release.ts +26 -55
  987. package/src/scripts/release_drill.ts +52 -23
  988. package/src/scripts/release_env.ts +37 -0
  989. package/src/scripts/release_publication.ts +11 -1
  990. package/src/scripts/report_consumer_gate_reach.ts +233 -0
  991. package/src/scripts/report_merge_gate_load.ts +295 -0
  992. package/src/scripts/report_project_contract.ts +123 -0
  993. package/src/scripts/report_reducible_classes.ts +342 -0
  994. package/src/scripts/report_required_checks_drift.ts +5 -3
  995. package/src/scripts/report_skill_host_census.ts +199 -0
  996. package/src/scripts/report_standing_payload_by_host.ts +7 -7
  997. package/src/scripts/retro.ts +758 -0
  998. package/src/scripts/retro_facts.ts +575 -0
  999. package/src/scripts/retro_queue.ts +739 -0
  1000. package/src/scripts/retro_session_facts.ts +218 -0
  1001. package/src/scripts/retro_sweep.ts +493 -0
  1002. package/src/scripts/retro_triage.ts +126 -0
  1003. package/src/scripts/roadmap_context.ts +2 -2
  1004. package/src/scripts/roadmap_drain_queue.ts +601 -0
  1005. package/src/scripts/run_supervise.ts +24 -2
  1006. package/src/scripts/schemas/agent-settings.schema.json +0 -16
  1007. package/src/scripts/schemas/command.schema.json +3 -3
  1008. package/src/scripts/schemas/review-findings.schema.json +8 -0
  1009. package/src/scripts/schemas/skill.schema.json +7 -6
  1010. package/src/scripts/schemas/subagent.schema.json +33 -2
  1011. package/src/scripts/score_skill_selection.ts +5 -2
  1012. package/src/scripts/second_brain_retrieval.ts +1 -0
  1013. package/src/scripts/second_brain_run.ts +1 -0
  1014. package/src/scripts/self_repair_cli.ts +563 -87
  1015. package/src/scripts/self_review_gate.ts +59 -4
  1016. package/src/scripts/session_register_hook.ts +91 -4
  1017. package/src/scripts/sessions_cli.ts +100 -5
  1018. package/src/scripts/skill_collision_clusters.ts +1 -1
  1019. package/src/scripts/skill_tools/score_skill_relevance.ts +31 -2
  1020. package/src/scripts/skill_trigger_eval.ts +4 -2
  1021. package/src/scripts/source_adapters.ts +183 -0
  1022. package/src/scripts/step_receipt.ts +100 -0
  1023. package/src/scripts/sync_pr_branch.ts +4 -0
  1024. package/src/scripts/test_council_qualification.ts +1 -1
  1025. package/src/scripts/trigger_eval_grandfather.json +3 -49
  1026. package/src/scripts/trigger_eval_rotation.ts +31 -3
  1027. package/src/scripts/ui_conformance_probe.ts +405 -1
  1028. package/src/scripts/update_counts.ts +230 -11
  1029. package/src/scripts/update_invite_hook.ts +245 -0
  1030. package/src/scripts/update_notice_hook.ts +298 -0
  1031. package/src/scripts/validate_frontmatter.ts +85 -0
  1032. package/src/scripts/worker_reuse_shadow_report.ts +121 -0
  1033. package/src/scripts/worktree_cleanup_check.ts +915 -121
  1034. package/src/server/io/yamlIO.ts +2 -2
  1035. package/src/server/schemas/settings.ts +37 -23
  1036. package/src/shared/brandTokenDocument.ts +46 -0
  1037. package/src/shared/brandTokenPaths.ts +43 -0
  1038. package/src/shared/settingsCarveOut.ts +0 -8
  1039. package/src/shared/skillRanking.ts +106 -5
  1040. package/src/shared/userMd/formAdapter.ts +15 -1
  1041. package/src/shared/userMd/schema.ts +22 -0
  1042. package/src/templates/agent-user.md +4 -0
  1043. package/src/templates/agent-user.yml +4 -0
  1044. package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
  1045. package/dist/cli-delegate/chunk-AL3RZ22D.js +0 -74
  1046. package/dist/cli-delegate/chunk-KB5FZ655.js +0 -208
  1047. package/dist/cli-delegate/chunk-MDPPKQCQ.js +0 -875
  1048. package/dist/cli-delegate/chunk-MSUL5NYP.js +0 -1123
  1049. package/dist/cli-delegate/chunk-OAFSJBHH.js +0 -272
  1050. package/dist/ui/assets/index-C3djEJah.js +0 -23
  1051. package/src/scripts/_lib/continuation_ladder.ts +0 -335
  1052. package/src/scripts/hooks/run_continuation_hook.ts +0 -1524
@@ -18,11 +18,18 @@
18
18
  * /worktree status + verify must surface).
19
19
  * inventory Classify EVERY worktree safe / review / live and
20
20
  * report the counts, the review reasons, and a
21
- * prepared removal plan for the safe set. Reporting
22
- * only — it never removes anything, because bulk
23
- * worktree + branch deletion is a Hard-Floor action
24
- * (`non-destructive-by-default`) that needs the
25
- * user's explicit this-turn approval.
21
+ * prepared removal plan for the safe set. Reports
22
+ * only.
23
+ * apply Remove the safe set: `git worktree remove` without
24
+ * `--force`, then `git worktree prune`, one journal
25
+ * line per removal. `safe` here is the scoped set the
26
+ * owner made housekeeping on 2026-10-21
27
+ * (road-to-worktrees-that-leave-after-the-merge D1):
28
+ * proven merged, clean, no local-only ignored file,
29
+ * not live. Every other removal stays a decision.
30
+ * Branches are never deleted by this tool.
31
+ * register <path> Record a worktree this package created, so a
32
+ * sibling outside the standard roots is eligible.
26
33
  *
27
34
  * Reachability counts ALL other refs — local branches, remotes, AND tags
28
35
  * (a branch whose only other ref is a tag is still reachable elsewhere).
@@ -34,7 +41,14 @@ import { execFileSync } from 'node:child_process';
34
41
  import * as fs from 'node:fs';
35
42
  import * as path from 'node:path';
36
43
  import { fileURLToPath, pathToFileURL } from 'node:url';
44
+ import { parse as parseYaml } from 'yaml';
45
+ import { load_agent_settings, settings_layer_states, user_global_settings_paths } from './_lib/agent_settings.js';
37
46
  import { read_live_records, register_dir } from './_lib/session_register.js';
47
+ import { git, gitEnv, timeLeftMs, tryGit, withDeadline } from './_lib/worktree_git.js';
48
+ import { localOnlyIgnored } from './_lib/worktree_ignored.js';
49
+
50
+ export { withDeadline } from './_lib/worktree_git.js';
51
+ export { localOnlyIgnored, REGENERABLE_IGNORED } from './_lib/worktree_ignored.js';
38
52
 
39
53
  export interface CheckResult {
40
54
  allowed: boolean;
@@ -46,21 +60,6 @@ export interface ScopeOverlap {
46
60
  b: { worktree: string; own: string };
47
61
  }
48
62
 
49
- function git(cwd: string, args: string[]): string {
50
- return execFileSync('git', ['-C', cwd, ...args], {
51
- encoding: 'utf-8',
52
- stdio: ['ignore', 'pipe', 'pipe'],
53
- });
54
- }
55
-
56
- function tryGit(cwd: string, args: string[]): string | null {
57
- try {
58
- return git(cwd, args);
59
- } catch {
60
- return null;
61
- }
62
- }
63
-
64
63
  /**
65
64
  * `git status` with the index left alone. Plain `git status` refreshes the
66
65
  * on-disk index, which bumps its mtime — and the inventory mode reads that
@@ -126,6 +125,8 @@ export interface WorktreeEntry {
126
125
  path: string;
127
126
  /** Short branch name (`refs/heads/` stripped), or `null` when detached. */
128
127
  branch: string | null;
128
+ /** `git worktree lock` was set on it — never removable here. */
129
+ locked?: boolean;
129
130
  }
130
131
 
131
132
  export function listWorktrees(repoPath: string): WorktreeEntry[] {
@@ -135,17 +136,19 @@ export function listWorktrees(repoPath: string): WorktreeEntry[] {
135
136
  for (const line of out.split('\n')) {
136
137
  if (line.startsWith('worktree ')) {
137
138
  if (current.path !== undefined) {
138
- entries.push({ path: current.path, branch: current.branch ?? null });
139
+ entries.push({ path: current.path, branch: current.branch ?? null, locked: current.locked === true });
139
140
  }
140
141
  current = { path: line.slice('worktree '.length) };
141
142
  } else if (line.startsWith('branch ')) {
142
143
  current.branch = line.slice('branch '.length).replace(/^refs\/heads\//, '');
143
144
  } else if (line === 'detached') {
144
145
  current.branch = null;
146
+ } else if (line === 'locked' || line.startsWith('locked ')) {
147
+ current.locked = true;
145
148
  }
146
149
  }
147
150
  if (current.path !== undefined) {
148
- entries.push({ path: current.path, branch: current.branch ?? null });
151
+ entries.push({ path: current.path, branch: current.branch ?? null, locked: current.locked === true });
149
152
  }
150
153
  return entries;
151
154
  }
@@ -266,7 +269,13 @@ export interface InventoryRow {
266
269
  reasons: string[];
267
270
  /** The branch is an ancestor of the trunk, so `git branch -d` is safe. */
268
271
  mergedIntoTrunk: boolean;
272
+ /** Strongest available proof the branch's work is on the trunk, or `null`. */
273
+ mergeEvidence: MergeEvidence | null;
274
+ /** Branch tip at inventory time — what a removal journals. */
275
+ tip: string | null;
269
276
  standardLocation: boolean;
277
+ /** A registration this package wrote names this worktree. */
278
+ registered: boolean;
270
279
  /** Main worktree — never removable, and never counted as residue. */
271
280
  isMain: boolean;
272
281
  }
@@ -274,6 +283,8 @@ export interface InventoryRow {
274
283
  export interface Inventory {
275
284
  trunk: string;
276
285
  rows: InventoryRow[];
286
+ /** What classified these rows — reused to re-check a row right before removal. */
287
+ context: ClassifyContext;
277
288
  counts: {
278
289
  total: number;
279
290
  safe: number;
@@ -306,6 +317,196 @@ function isAncestor(repoPath: string, branch: string, trunk: string): boolean {
306
317
  }
307
318
  }
308
319
 
320
+ /**
321
+ * How a branch's work is known to be on the trunk, strongest first.
322
+ *
323
+ * `merged-ancestor` is the graph proof. It never holds for a squash merge,
324
+ * which is how most PRs on a squash-merging trunk land — so on its own it
325
+ * classed every one of them as unmerged work forever. `merged-pr` is the forge
326
+ * proof: the host reports the branch's PR MERGED **and** the branch tip still
327
+ * equals that PR's head, so no commit was made after the merge. `merged-
328
+ * equivalent` is the offline proof, used only when the forge cannot be read:
329
+ * merging the branch into the trunk produces the trunk's own tree, so nothing
330
+ * on the branch is missing from it. `closed-unmerged` is never removed.
331
+ */
332
+ export type MergeEvidence = 'merged-ancestor' | 'merged-pr' | 'merged-equivalent' | 'closed-unmerged';
333
+
334
+ export interface PrRecord {
335
+ state: 'MERGED' | 'CLOSED' | 'OPEN';
336
+ headOid: string;
337
+ mergedAt: string | null;
338
+ /** The PR's base branch; a merge into another branch proves nothing about the trunk. */
339
+ base: string | null;
340
+ }
341
+
342
+ /** PR records keyed by head branch name. `null` means the forge was not read. */
343
+ export type PrIndex = Map<string, PrRecord[]>;
344
+
345
+ export type GhRunner = (args: string[], timeoutMs: number) => string;
346
+
347
+ const defaultGh =
348
+ (cwd: string): GhRunner =>
349
+ (args, timeoutMs) =>
350
+ execFileSync('gh', args, {
351
+ cwd,
352
+ encoding: 'utf-8',
353
+ stdio: ['ignore', 'pipe', 'ignore'],
354
+ timeout: timeoutMs,
355
+ env: gitEnv(),
356
+ });
357
+
358
+ /**
359
+ * ONE forge read for the whole estate. The retro reads PR state per PR, which
360
+ * scales with the number of worktrees; an estate of dozens needs one list call.
361
+ * Any failure — no `gh`, no login, no network, a timeout — returns `null`, and
362
+ * the caller falls back to the offline proof rather than guessing.
363
+ */
364
+ export function readPrIndex(
365
+ repoPath: string,
366
+ opts: { run?: GhRunner; timeoutMs?: number; limit?: number } = {},
367
+ ): PrIndex | null {
368
+ const run = opts.run ?? defaultGh(repoPath);
369
+ try {
370
+ const raw = run(
371
+ ['pr', 'list', '--state', 'all', '--limit', String(opts.limit ?? 1000), '--json', 'headRefName,headRefOid,state,mergedAt,baseRefName'],
372
+ Math.min(opts.timeoutMs ?? 15000, timeLeftMs() ?? Number.POSITIVE_INFINITY),
373
+ );
374
+ const rows = JSON.parse(raw) as Array<{
375
+ headRefName?: string;
376
+ headRefOid?: string;
377
+ state?: string;
378
+ mergedAt?: string | null;
379
+ baseRefName?: string;
380
+ }>;
381
+ if (!Array.isArray(rows)) return null;
382
+ const index: PrIndex = new Map();
383
+ for (const r of rows) {
384
+ if (typeof r.headRefName !== 'string' || typeof r.headRefOid !== 'string') continue;
385
+ if (r.state !== 'MERGED' && r.state !== 'CLOSED' && r.state !== 'OPEN') continue;
386
+ const list = index.get(r.headRefName) ?? [];
387
+ list.push({
388
+ state: r.state,
389
+ headOid: r.headRefOid,
390
+ mergedAt: typeof r.mergedAt === 'string' ? r.mergedAt : null,
391
+ base: typeof r.baseRefName === 'string' ? r.baseRefName : null,
392
+ });
393
+ index.set(r.headRefName, list);
394
+ }
395
+ return index;
396
+ } catch {
397
+ return null;
398
+ }
399
+ }
400
+
401
+ function branchTip(repoPath: string, branch: string): string | null {
402
+ const out = tryGit(repoPath, ['rev-parse', '--verify', '--quiet', `refs/heads/${branch}`]);
403
+ return out === null ? null : out.trim();
404
+ }
405
+
406
+ /** Merging `branch` into `trunk` yields the trunk's own tree. */
407
+ function mergeEquivalent(repoPath: string, branch: string, trunk: string): boolean {
408
+ const merged = tryGit(repoPath, ['merge-tree', '--write-tree', trunk, branch]);
409
+ const trunkTree = tryGit(repoPath, ['rev-parse', `${trunk}^{tree}`]);
410
+ if (merged === null || trunkTree === null) return false;
411
+ return merged.split('\n')[0]!.trim() === trunkTree.trim();
412
+ }
413
+
414
+ export interface MergeVerdict {
415
+ evidence: MergeEvidence | null;
416
+ /** When the forge recorded the merge; `null` for the graph and offline proofs. */
417
+ mergedAt: string | null;
418
+ }
419
+
420
+ export function mergeEvidence(
421
+ repoPath: string,
422
+ branch: string,
423
+ trunk: string,
424
+ prIndex: PrIndex | null,
425
+ ): MergeVerdict {
426
+ if (isAncestor(repoPath, branch, trunk)) return { evidence: 'merged-ancestor', mergedAt: null };
427
+ if (prIndex !== null) {
428
+ const tip = branchTip(repoPath, branch);
429
+ // `refs/remotes/origin/main`, `refs/heads/main` and the short `origin/main`
430
+ // a `--trunk=` flag may pass all name the base branch `main`.
431
+ const trunkName = trunk.replace(/^refs\/(?:remotes\/[^/]+|heads)\//, '').replace(/^(?:origin|upstream)\//, '');
432
+ // Only a PR into the trunk speaks for the trunk; one merged into a
433
+ // release branch is not a record of this branch at all.
434
+ const prs = (prIndex.get(branch) ?? []).filter((p) => p.base === trunkName);
435
+ const merged = prs.find((p) => p.state === 'MERGED' && p.headOid === tip);
436
+ if (merged !== undefined) return { evidence: 'merged-pr', mergedAt: merged.mergedAt };
437
+ if (prs.length > 0 && prs.every((p) => p.state === 'CLOSED')) {
438
+ return { evidence: 'closed-unmerged', mergedAt: null };
439
+ }
440
+ // A PR record exists but none merged at this tip: the forge has spoken.
441
+ if (prs.length > 0) return { evidence: null, mergedAt: null };
442
+ // No record at all — the PR is older than the window read, or the branch
443
+ // never had one. The tree proof is still a proof, so fall through to it.
444
+ }
445
+ if (mergeEquivalent(repoPath, branch, trunk)) return { evidence: 'merged-equivalent', mergedAt: null };
446
+ return { evidence: null, mergedAt: null };
447
+ }
448
+
449
+ /** One line per worktree this package created, in the repository's common git dir. */
450
+ export const REGISTRY_FILE = 'agent-config-worktrees.jsonl';
451
+ /** One line per worktree this tool removed — the tip SHA recreates the branch. */
452
+ export const REMOVAL_JOURNAL = 'agent-config-worktree-removals.jsonl';
453
+
454
+ function commonDir(repoPath: string): string | null {
455
+ const out = tryGit(repoPath, ['rev-parse', '--path-format=absolute', '--git-common-dir']);
456
+ return out === null ? null : out.trim();
457
+ }
458
+
459
+ export interface RegistryEntry {
460
+ path: string;
461
+ branch: string | null;
462
+ created_by: 'agent-config';
463
+ purpose: string;
464
+ at: string;
465
+ }
466
+
467
+ export function registerWorktree(repoPath: string, worktreePath: string, purpose: string, now = new Date()): RegistryEntry {
468
+ const dir = commonDir(repoPath);
469
+ if (dir === null) throw new Error(`not a git repository: ${repoPath}`);
470
+ const headRef = tryGit(worktreePath, ['symbolic-ref', '-q', '--short', 'HEAD']);
471
+ const entry: RegistryEntry = {
472
+ path: canonical(worktreePath),
473
+ branch: headRef === null ? null : headRef.trim(),
474
+ created_by: 'agent-config',
475
+ purpose,
476
+ at: now.toISOString(),
477
+ };
478
+ fs.appendFileSync(path.join(dir, REGISTRY_FILE), `${JSON.stringify(entry)}\n`);
479
+ return entry;
480
+ }
481
+
482
+ export function readRegistry(repoPath: string): Set<string> {
483
+ const dir = commonDir(repoPath);
484
+ const paths = new Set<string>();
485
+ if (dir === null) return paths;
486
+ let text = '';
487
+ try {
488
+ text = fs.readFileSync(path.join(dir, REGISTRY_FILE), 'utf-8');
489
+ } catch {
490
+ return paths;
491
+ }
492
+ for (const line of text.split('\n')) {
493
+ try {
494
+ const e = JSON.parse(line) as Partial<RegistryEntry>;
495
+ if (e.created_by === 'agent-config' && typeof e.path === 'string') paths.add(canonical(e.path));
496
+ } catch {
497
+ /* a torn or foreign line is not a registration */
498
+ }
499
+ }
500
+ return paths;
501
+ }
502
+
503
+ /** `../<repo>-<suffix>` beside the main checkout: the shape this package's lanes use. */
504
+ export function isRepoSibling(mainPath: string, worktreePath: string): boolean {
505
+ const main = canonical(mainPath);
506
+ const wt = canonical(worktreePath);
507
+ return path.dirname(main) === path.dirname(wt) && path.basename(wt).startsWith(`${path.basename(main)}-`);
508
+ }
509
+
309
510
  /**
310
511
  * `basePath` MUST be the main worktree, never the invoking repo path.
311
512
  *
@@ -380,6 +581,186 @@ export interface InventoryOptions {
380
581
  now?: Date;
381
582
  minAgeDays?: number | null;
382
583
  excludeLiveSessions?: boolean;
584
+ /**
585
+ * Forge PR records for the squash-aware proof. `undefined` and `null` both
586
+ * mean "not read": the inventory then uses the graph and offline proofs only.
587
+ */
588
+ prIndex?: PrIndex | null;
589
+ /**
590
+ * Hours a forge-proven merge must age before removal (D4). `0` on the
591
+ * `/pr:merge` path, where the session that merged has nothing left to do.
592
+ */
593
+ mergeDelayHours?: number;
594
+ /** Override the trunk ref (default: origin/main → origin/master → main → master). */
595
+ trunk?: string;
596
+ /** See `ClassifyContext.mergedBranch`. */
597
+ mergedBranch?: string | null;
598
+ /** See `ClassifyContext.selfSessionId`. */
599
+ selfSessionId?: string | null;
600
+ }
601
+
602
+ /** D4 — a revert or follow-up can reuse the tree for a day. */
603
+ export const MERGE_DELAY_HOURS = 24;
604
+
605
+ export interface ClassifyContext {
606
+ trunk: string;
607
+ mainPath: string;
608
+ now: Date;
609
+ liveCutoff: number;
610
+ sessionPaths: Set<string>;
611
+ registry: Set<string>;
612
+ ageCutoff: number | null;
613
+ minAgeDays: number | null;
614
+ forge: { prIndex: PrIndex | null; mergeDelayHours: number };
615
+ /**
616
+ * The branch whose merge the calling session itself just performed
617
+ * (`/pr:merge`). Its git-dir mtimes are that merge work, not another
618
+ * session, so the mtime fallback is skipped for it; every other gate,
619
+ * the session register included, still applies.
620
+ */
621
+ mergedBranch?: string | null;
622
+ /** The calling session's own register id, never counted as "another session". */
623
+ selfSessionId?: string | null;
624
+ /** Read sessions from the register (re-read before each removal). */
625
+ readSessions?: boolean;
626
+ }
627
+
628
+ /** Live session worktrees from the register, minus the caller's own session. */
629
+ export function liveSessionPaths(mainPath: string, now: Date, selfSessionId: string | null = null): Set<string> {
630
+ const out = new Set<string>();
631
+ const dir = register_dir(mainPath);
632
+ if (dir === null) return out;
633
+ for (const rec of read_live_records(dir, { now })) {
634
+ if (selfSessionId !== null && rec.session_id === selfSessionId) continue;
635
+ out.add(canonical(rec.worktree));
636
+ }
637
+ return out;
638
+ }
639
+
640
+ /** One worktree, classified. Shared by the inventory and by the re-check run immediately before a removal. */
641
+ export function classifyEntry(e: WorktreeEntry, ctx: ClassifyContext): InventoryRow {
642
+ const { trunk, mainPath, now, liveCutoff, sessionPaths, registry, ageCutoff, minAgeDays, forge } = ctx;
643
+ const resolved = canonical(e.path);
644
+ const isMain = resolved === mainPath;
645
+ // `mainPath`, NOT `repoPath` — see isStandardLocation's contract.
646
+ const standardLocation = isMain ? true : isStandardLocation(mainPath, resolved);
647
+ const registered = registry.has(resolved);
648
+ const reasons: string[] = [];
649
+ const base = { path: e.path, branch: e.branch, standardLocation, registered, isMain };
650
+
651
+ if (!fs.existsSync(resolved)) {
652
+ return {
653
+ ...base,
654
+ classification: 'review',
655
+ reasons: ['registration points at a missing directory — `git worktree prune` clears it'],
656
+ mergedIntoTrunk: false,
657
+ mergeEvidence: null,
658
+ tip: null,
659
+ };
660
+ }
661
+
662
+ const tip = e.branch === null ? null : branchTip(resolved, e.branch);
663
+ // The session register is the primary liveness source; a registered
664
+ // session in the tree makes it live whatever its mtimes say.
665
+ if (sessionPaths.has(resolved)) {
666
+ return {
667
+ ...base,
668
+ classification: 'live',
669
+ reasons: ['a live agent session is registered in this worktree'],
670
+ mergedIntoTrunk: e.branch !== null && isAncestor(resolved, e.branch, trunk),
671
+ mergeEvidence: null,
672
+ tip,
673
+ };
674
+ }
675
+ // Fallback for sessions the register cannot see (another host, a plain
676
+ // terminal): recent git activity in the per-worktree git dir.
677
+ const activity = lastGitActivity(resolved);
678
+ const ownMerge = ctx.mergedBranch !== undefined && ctx.mergedBranch !== null && e.branch === ctx.mergedBranch;
679
+ if (!ownMerge && activity !== null && activity.getTime() >= liveCutoff) {
680
+ return {
681
+ ...base,
682
+ classification: 'live',
683
+ reasons: [`git activity within the last ${LIVE_WINDOW_HOURS}h — another session may hold it`],
684
+ mergedIntoTrunk: e.branch !== null && isAncestor(resolved, e.branch, trunk),
685
+ mergeEvidence: null,
686
+ tip,
687
+ };
688
+ }
689
+
690
+ if (isMain) reasons.push('main worktree — cannot be removed');
691
+ if (e.locked === true) reasons.push('locked (`git worktree unlock` first) — never removed here');
692
+ if (e.branch === null) {
693
+ reasons.push('detached HEAD — no branch to judge reachability for');
694
+ }
695
+ if (ageCutoff !== null && (activity === null || activity.getTime() >= ageCutoff)) {
696
+ // `activity === null` disqualifies rather than passes: an unreadable
697
+ // git-dir mtime is absence of evidence, and under an explicit
698
+ // minimum-age floor that has to read as "cannot show it is old
699
+ // enough", never as "old enough".
700
+ reasons.push(
701
+ activity === null
702
+ ? `git activity unreadable — cannot prove ${minAgeDays}+ days of inactivity`
703
+ : `git activity within the last ${minAgeDays} days`,
704
+ );
705
+ }
706
+ const verdict =
707
+ e.branch === null
708
+ ? { evidence: null, mergedAt: null }
709
+ : mergeEvidence(resolved, e.branch, trunk, forge.prIndex);
710
+ const mergedIntoTrunk = verdict.evidence === 'merged-ancestor';
711
+ const proven =
712
+ verdict.evidence === 'merged-ancestor' ||
713
+ verdict.evidence === 'merged-pr' ||
714
+ verdict.evidence === 'merged-equivalent';
715
+
716
+ // Outside the standard roots a tree is eligible only by a registration
717
+ // this package wrote, or by the `<repo>-*` sibling shape plus a merge
718
+ // proof (D2). Location alone never qualifies, and never disqualifies a
719
+ // tree this package created.
720
+ if (!standardLocation && !registered && !(proven && isRepoSibling(mainPath, resolved))) {
721
+ reasons.push('non-standard location — outside the conventional worktree roots');
722
+ }
723
+
724
+ if (e.branch !== null && verdict.evidence === 'closed-unmerged') {
725
+ reasons.push('PR closed unmerged — the work is not on the trunk');
726
+ } else if (e.branch !== null && !proven) {
727
+ reasons.push(`branch is not an ancestor of ${trunk} — unmerged work`);
728
+ const gate = checkWorktree(resolved);
729
+ if (!gate.allowed) reasons.push(...gate.reasons);
730
+ } else if (e.branch !== null) {
731
+ // A proven merge makes the unique-commit gate moot: an ancestor has
732
+ // every commit on the trunk, and a squash- or tree-proven branch's
733
+ // commits are exactly what the trunk already holds as one commit.
734
+ const status = statusPorcelain(resolved);
735
+ if (status.trim().length > 0) {
736
+ const n = status.trimEnd().split('\n').length;
737
+ reasons.push(`unsaved work — ${n} dirty or untracked path(s)`);
738
+ }
739
+ const local = localOnlyIgnored(resolved, trunk);
740
+ if (local.length > 0) {
741
+ const shown = local.slice(0, 5).join(', ');
742
+ reasons.push(`local-only files — ${local.length} ignored path(s) a rebuild would not restore: ${shown}`);
743
+ }
744
+ if (verdict.evidence === 'merged-pr' && forge.mergeDelayHours > 0) {
745
+ // The forge proof carries its own clock; an absent or unparseable
746
+ // merge time cannot show the delay has passed, so it keeps the tree.
747
+ const age = verdict.mergedAt === null ? Number.NaN : now.getTime() - Date.parse(verdict.mergedAt);
748
+ if (!Number.isFinite(age)) {
749
+ reasons.push('merge time unreadable — cannot show the follow-up delay has passed');
750
+ } else if (age < forge.mergeDelayHours * 3600 * 1000) {
751
+ reasons.push(`merged less than ${forge.mergeDelayHours}h ago — kept for a follow-up`);
752
+ }
753
+ }
754
+ }
755
+
756
+ return {
757
+ ...base,
758
+ classification: reasons.length === 0 ? 'safe' : 'review',
759
+ reasons,
760
+ mergedIntoTrunk,
761
+ mergeEvidence: verdict.evidence,
762
+ tip,
763
+ };
383
764
  }
384
765
 
385
766
  export function buildInventory(
@@ -391,7 +772,13 @@ export function buildInventory(
391
772
  const now = opts.now ?? new Date();
392
773
  const minAgeDays = opts.minAgeDays ?? null;
393
774
  const ageCutoff = minAgeDays === null ? null : now.getTime() - minAgeDays * 86400 * 1000;
394
- return buildInventoryInner(repoPath, now, ageCutoff, minAgeDays, opts.excludeLiveSessions === true);
775
+ return buildInventoryInner(repoPath, now, ageCutoff, minAgeDays, opts.excludeLiveSessions === true, {
776
+ prIndex: opts.prIndex ?? null,
777
+ mergeDelayHours: opts.mergeDelayHours ?? MERGE_DELAY_HOURS,
778
+ trunk: opts.trunk ?? null,
779
+ mergedBranch: opts.mergedBranch ?? null,
780
+ selfSessionId: opts.selfSessionId ?? null,
781
+ });
395
782
  }
396
783
 
397
784
  function buildInventoryInner(
@@ -400,9 +787,10 @@ function buildInventoryInner(
400
787
  ageCutoff: number | null,
401
788
  minAgeDays: number | null,
402
789
  excludeLiveSessions: boolean,
790
+ forge: { prIndex: PrIndex | null; mergeDelayHours: number; trunk: string | null; mergedBranch: string | null; selfSessionId: string | null },
403
791
  ): Inventory {
404
792
  const now = nowArg;
405
- const trunk = resolveTrunk(repoPath);
793
+ const trunk = forge.trunk ?? resolveTrunk(repoPath);
406
794
  const entries = listWorktrees(repoPath);
407
795
  const mainPath = canonical(entries.length > 0 ? entries[0]!.path : repoPath);
408
796
  const liveCutoff = now.getTime() - LIVE_WINDOW_HOURS * 3600 * 1000;
@@ -413,96 +801,19 @@ function buildInventoryInner(
413
801
  // state before any session registers), or when every record has expired.
414
802
  const sessionPaths = new Set<string>();
415
803
  if (excludeLiveSessions) {
416
- const dir = register_dir(mainPath);
417
- if (dir !== null) {
418
- for (const rec of read_live_records(dir, { now })) {
419
- sessionPaths.add(canonical(rec.worktree));
420
- }
421
- }
804
+ for (const p of liveSessionPaths(mainPath, now, forge.selfSessionId ?? null)) sessionPaths.add(p);
422
805
  }
423
806
 
424
- const rows: InventoryRow[] = entries.map((e) => {
425
- const resolved = canonical(e.path);
426
- const isMain = resolved === mainPath;
427
- // `mainPath`, NOT `repoPath` — see isStandardLocation's contract.
428
- const standardLocation = isMain ? true : isStandardLocation(mainPath, resolved);
429
- const reasons: string[] = [];
430
-
431
- if (!fs.existsSync(resolved)) {
432
- return {
433
- path: e.path,
434
- branch: e.branch,
435
- classification: 'review',
436
- reasons: ['registration points at a missing directory — `git worktree prune` clears it'],
437
- mergedIntoTrunk: false,
438
- standardLocation,
439
- isMain,
440
- };
441
- }
442
-
443
- const activity = lastGitActivity(resolved);
444
- if (activity !== null && activity.getTime() >= liveCutoff) {
445
- return {
446
- path: e.path,
447
- branch: e.branch,
448
- classification: 'live',
449
- reasons: [`git activity within the last ${LIVE_WINDOW_HOURS}h — another session may hold it`],
450
- mergedIntoTrunk: e.branch !== null && isAncestor(resolved, e.branch, trunk),
451
- standardLocation,
452
- isMain,
453
- };
454
- }
807
+ const registry = readRegistry(mainPath);
455
808
 
456
- if (isMain) reasons.push('main worktree — cannot be removed');
457
- if (e.branch === null) {
458
- reasons.push('detached HEAD — no branch to judge reachability for');
459
- }
460
- if (sessionPaths.has(resolved)) {
461
- reasons.push('a live agent session is registered in this worktree');
462
- }
463
- if (ageCutoff !== null && (activity === null || activity.getTime() >= ageCutoff)) {
464
- // `activity === null` disqualifies rather than passes: an unreadable
465
- // git-dir mtime is absence of evidence, and under an explicit
466
- // minimum-age floor that has to read as "cannot show it is old
467
- // enough", never as "old enough".
468
- reasons.push(
469
- activity === null
470
- ? `git activity unreadable — cannot prove ${minAgeDays}+ days of inactivity`
471
- : `git activity within the last ${minAgeDays} days`,
472
- );
473
- }
474
- if (!standardLocation) {
475
- reasons.push('non-standard location — outside the conventional worktree roots');
476
- }
477
-
478
- const mergedIntoTrunk = e.branch !== null && isAncestor(resolved, e.branch, trunk);
479
-
480
- // A branch that is an ancestor of the trunk has every commit reachable
481
- // from the trunk ref, so the expensive rev-list gate cannot find a
482
- // unique commit. Only run it for the branches that are NOT merged —
483
- // that is where it can actually refuse.
484
- if (e.branch !== null && !mergedIntoTrunk) {
485
- reasons.push(`branch is not an ancestor of ${trunk} — unmerged work`);
486
- const gate = checkWorktree(resolved);
487
- if (!gate.allowed) reasons.push(...gate.reasons);
488
- } else if (e.branch !== null) {
489
- const status = statusPorcelain(resolved);
490
- if (status.trim().length > 0) {
491
- const n = status.trimEnd().split('\n').length;
492
- reasons.push(`unsaved work — ${n} dirty or untracked path(s)`);
493
- }
494
- }
495
-
496
- return {
497
- path: e.path,
498
- branch: e.branch,
499
- classification: reasons.length === 0 ? 'safe' : 'review',
500
- reasons,
501
- mergedIntoTrunk,
502
- standardLocation,
503
- isMain,
504
- };
505
- });
809
+ const ctx: ClassifyContext = {
810
+ trunk, mainPath, now, liveCutoff, sessionPaths, registry, ageCutoff, minAgeDays,
811
+ forge: { prIndex: forge.prIndex, mergeDelayHours: forge.mergeDelayHours },
812
+ mergedBranch: forge.mergedBranch,
813
+ selfSessionId: forge.selfSessionId,
814
+ readSessions: excludeLiveSessions,
815
+ };
816
+ const rows: InventoryRow[] = entries.map((e) => classifyEntry(e, ctx));
506
817
 
507
818
  const reviewReasons: Record<string, number> = {};
508
819
  for (const r of rows) {
@@ -516,6 +827,7 @@ function buildInventoryInner(
516
827
  return {
517
828
  trunk,
518
829
  rows,
830
+ context: ctx,
519
831
  counts: {
520
832
  total: rows.length,
521
833
  safe: rows.filter((r) => r.classification === 'safe').length,
@@ -528,6 +840,15 @@ function buildInventoryInner(
528
840
  };
529
841
  }
530
842
 
843
+ /**
844
+ * One argv element for a printed POSIX shell line, always single-quoted. A
845
+ * branch name can come from a pull request's author, and git allows `$`, `(`,
846
+ * `)` and backticks in it, so double quotes would let a copied line run it.
847
+ */
848
+ export function shQuote(arg: string): string {
849
+ return `'${arg.replaceAll("'", `'\\''`)}'`;
850
+ }
851
+
531
852
  /**
532
853
  * The removal commands for the safe set — printed for a human to review and
533
854
  * run, never executed here. `git branch -d` (never `-D`) so git itself
@@ -537,17 +858,417 @@ export function removalPlan(inv: Inventory): string[] {
537
858
  return inv.rows
538
859
  .filter((r) => r.classification === 'safe')
539
860
  .map((r) => {
540
- const remove = `git worktree remove ${JSON.stringify(r.path)}`;
861
+ const remove = `git worktree remove ${shQuote(r.path)}`;
541
862
  return r.branch !== null && r.mergedIntoTrunk
542
- ? `${remove} && git branch -d ${JSON.stringify(r.branch)}`
863
+ ? `${remove} && git branch -d ${shQuote(r.branch)}`
543
864
  : remove;
544
865
  });
545
866
  }
546
867
 
868
+ export interface RemovalOutcome {
869
+ path: string;
870
+ branch: string | null;
871
+ tip: string | null;
872
+ evidence: MergeEvidence | null;
873
+ removed: boolean;
874
+ /** git's own refusal text when it declined, e.g. a tree that turned dirty. */
875
+ error: string | null;
876
+ }
877
+
878
+ /** Per-repository removal lock in the common git dir; stale after this long. */
879
+ export const REMOVAL_LOCK = 'agent-config-worktree-removal.lock';
880
+ const LOCK_STALE_MS = 10 * 60 * 1000;
881
+
882
+ /**
883
+ * Take the per-repository removal lock, or `null` when another pass holds it.
884
+ * Two session starts in two worktrees of one repository must not both judge and
885
+ * remove the same tree; the second one simply does nothing this time.
886
+ */
887
+ function takeRemovalLock(mainPath: string, now: Date): (() => void) | null {
888
+ const dir = commonDir(mainPath);
889
+ if (dir === null) return null;
890
+ const file = path.join(dir, REMOVAL_LOCK);
891
+ // The token names THIS holder: release deletes the lock only while it is
892
+ // still ours, so a pass that outlived the stale window cannot delete the
893
+ // lock a later pass took over.
894
+ const token = `${process.pid} ${now.toISOString()} ${Math.random().toString(36).slice(2)}`;
895
+ const tryCreate = (): boolean => {
896
+ try {
897
+ fs.writeFileSync(file, `${token}\n`, { flag: 'wx' });
898
+ return true;
899
+ } catch {
900
+ return false;
901
+ }
902
+ };
903
+ if (!tryCreate()) {
904
+ try {
905
+ if (now.getTime() - fs.statSync(file).mtimeMs < LOCK_STALE_MS) return null;
906
+ // Unlink only the stale lock that was judged: a pass that took it over
907
+ // in between wrote a new token, and that lock is not ours to delete.
908
+ const judged = fs.readFileSync(file, 'utf-8');
909
+ const aside = `${file}.${process.pid}.stale`;
910
+ fs.renameSync(file, aside);
911
+ if (fs.readFileSync(aside, 'utf-8') !== judged) {
912
+ fs.renameSync(aside, file);
913
+ return null;
914
+ }
915
+ fs.unlinkSync(aside);
916
+ } catch {
917
+ return null;
918
+ }
919
+ if (!tryCreate()) return null;
920
+ }
921
+ return () => {
922
+ try {
923
+ if (fs.readFileSync(file, 'utf-8').trim() === token) fs.unlinkSync(file);
924
+ } catch {
925
+ /* already gone — a stale-lock sweep by another pass */
926
+ }
927
+ };
928
+ }
929
+
930
+ /**
931
+ * Remove the safe set. Plain `git worktree remove`, without the force flag, so git
932
+ * re-checks cleanliness itself at the moment of removal. Before that, every
933
+ * candidate is classified AGAIN, immediately before its own removal, under the
934
+ * repository lock: a tree that turned dirty, gained a local-only file, gained a
935
+ * session or moved its tip since the inventory is kept (council 2026-10-21,
936
+ * check-to-remove). The main worktree and every non-safe row are untouchable
937
+ * here by construction. Branches are left alone (D3); the journal carries the
938
+ * tip SHA, which is enough to recreate one.
939
+ */
940
+ export function applyRemovals(
941
+ repoPath: string,
942
+ inv: Inventory,
943
+ opts: { onlyBranch?: string | null; now?: Date; recheck?: ClassifyContext; limit?: number; here?: string } = {},
944
+ ): RemovalOutcome[] {
945
+ const now = opts.now ?? new Date();
946
+ const mainPath = inv.rows.find((r) => r.isMain)?.path ?? repoPath;
947
+ // Never the tree the caller is standing in: a session started inside a merged
948
+ // worktree would lose its own working directory.
949
+ const here = canonical(opts.here ?? process.cwd());
950
+ const inside = (p: string): boolean => {
951
+ const t = canonical(p);
952
+ return here === t || here.startsWith(t + path.sep);
953
+ };
954
+ const rows = inv.rows
955
+ .filter(
956
+ (r) =>
957
+ r.classification === 'safe' &&
958
+ !r.isMain &&
959
+ !inside(r.path) &&
960
+ (opts.onlyBranch === undefined || opts.onlyBranch === null || r.branch === opts.onlyBranch),
961
+ )
962
+ .slice(0, opts.limit ?? Number.POSITIVE_INFINITY);
963
+ if (rows.length === 0) return [];
964
+ const release = takeRemovalLock(mainPath, now);
965
+ if (release === null) return [];
966
+ const outcomes: RemovalOutcome[] = [];
967
+ const dir = commonDir(mainPath);
968
+ // Write-ahead: an `intent` line with the tip goes down BEFORE the removal and
969
+ // the outcome line after it, so a crash between the two still leaves the SHA
970
+ // that recreates the branch.
971
+ const journal = (o: RemovalOutcome, phase: 'intent' | 'outcome'): void => {
972
+ if (dir === null) return;
973
+ const line = JSON.stringify({ v: 1, phase, at: new Date().toISOString(), path: o.path, branch: o.branch, tip: o.tip, evidence: o.evidence, removed: o.removed, error: o.error });
974
+ try {
975
+ fs.appendFileSync(path.join(dir, REMOVAL_JOURNAL), `${line}\n`);
976
+ } catch {
977
+ /* an unwritable journal never blocks a removal git already judged safe */
978
+ }
979
+ };
980
+ try {
981
+ const base = opts.recheck ?? inv.context;
982
+ for (const r of rows) {
983
+ let error: string | null = null;
984
+ // The register is read AGAIN for every candidate: a session that
985
+ // entered the tree after the inventory makes it live here.
986
+ const ctx: ClassifyContext =
987
+ base.readSessions === true ? { ...base, sessionPaths: liveSessionPaths(base.mainPath, new Date(), base.selfSessionId ?? null) } : base;
988
+ // The entry is read AGAIN too: a tree switched to another branch or
989
+ // to a detached commit since the inventory is judged as it is now,
990
+ // never by the branch it had then.
991
+ let again: InventoryRow | null = null;
992
+ try {
993
+ const fresh = listWorktrees(mainPath).find((e) => canonical(e.path) === canonical(r.path));
994
+ const head = tryGit(canonical(r.path), ['rev-parse', '--verify', '--quiet', 'HEAD']);
995
+ if (fresh !== undefined && fresh.branch === r.branch && head !== null && head.trim() === r.tip) {
996
+ // The re-check carries a deadline of its own, so one hanging
997
+ // `git status` cannot hold a session start; the removal after
998
+ // it has the fixed REMOVAL_TIMEOUT_MS instead.
999
+ again = withDeadline(Date.now() + RECHECK_BUDGET_MS, () => classifyEntry(fresh, ctx));
1000
+ } else {
1001
+ error = 'HEAD or branch changed since the inventory — kept';
1002
+ }
1003
+ } catch {
1004
+ again = null;
1005
+ }
1006
+ if (error !== null) {
1007
+ /* recorded below */
1008
+ } else if (again === null) {
1009
+ error = 'could not re-check it — kept';
1010
+ } else if (again.classification !== 'safe' || again.tip !== r.tip) {
1011
+ error = `changed since the inventory — kept (${again.reasons[0] ?? 'tip moved'})`;
1012
+ } else {
1013
+ journal({ path: r.path, branch: r.branch, tip: again.tip, evidence: again.mergeEvidence, removed: false, error: null }, 'intent');
1014
+ try {
1015
+ // A fixed, generous timeout of its own: a removal is never
1016
+ // cut short by the classification budget mid-deletion.
1017
+ execFileSync('git', ['-C', mainPath, 'worktree', 'remove', r.path], {
1018
+ encoding: 'utf-8',
1019
+ stdio: ['ignore', 'pipe', 'pipe'],
1020
+ env: gitEnv(),
1021
+ timeout: REMOVAL_TIMEOUT_MS,
1022
+ });
1023
+ } catch (e) {
1024
+ const stderr = (e as { stderr?: Buffer | string }).stderr;
1025
+ error = (stderr === undefined ? String(e) : String(stderr)).trim().split('\n')[0] ?? 'refused';
1026
+ }
1027
+ }
1028
+ const o: RemovalOutcome = {
1029
+ path: r.path,
1030
+ branch: r.branch,
1031
+ tip: again?.tip ?? r.tip,
1032
+ evidence: again?.mergeEvidence ?? r.mergeEvidence,
1033
+ removed: error === null,
1034
+ error,
1035
+ };
1036
+ outcomes.push(o);
1037
+ journal(o, 'outcome');
1038
+ }
1039
+ // No `git worktree prune` here: it is repository-wide, and a tree on an
1040
+ // unmounted volume would lose its registration without ever having been
1041
+ // judged. `git worktree remove` already drops the entry it removes.
1042
+ } finally {
1043
+ release();
1044
+ }
1045
+ return outcomes;
1046
+ }
1047
+
1048
+ /** Per-candidate re-check deadline, separate from the removal's own timeout. */
1049
+ export const RECHECK_BUDGET_MS = 3000;
1050
+ /** Per-removal timeout, independent of any classification budget. */
1051
+ export const REMOVAL_TIMEOUT_MS = 30000;
1052
+ /** The daily pass removes at most this many trees; the rest wait for tomorrow or `apply`. */
1053
+ export const DAILY_REMOVAL_CAP = 3;
1054
+
1055
+ /** The one line a session start or a merge prints after a removal pass. */
1056
+ export function removalSummary(inv: Inventory, outcomes: RemovalOutcome[], opts: { names?: boolean } = {}): string {
1057
+ const removed = outcomes.filter((o) => o.removed).length;
1058
+ const decide = inv.rows.filter((r) => r.classification === 'review' && !r.isMain).length;
1059
+ const branches = outcomes
1060
+ .filter((o) => o.removed && o.branch !== null && o.evidence !== 'merged-ancestor')
1061
+ .map((o) => o.branch!);
1062
+ // Branch names stay out of what a session start injects; the CLI, run on
1063
+ // purpose, prints them so the cleanup command can be copied.
1064
+ const hint =
1065
+ branches.length === 0
1066
+ ? ''
1067
+ : opts.names === false
1068
+ ? ` · ${branches.length} local branch(es) kept (the removal journal names them)`
1069
+ : ` · local branches kept: git branch -D ${branches.map(shQuote).join(' ')}`;
1070
+ return `worktrees: ${removed} removed, ${decide} need a decision (/worktree cleanup)${hint}`;
1071
+ }
1072
+
1073
+ export type CleanupMode = 'auto' | 'notify' | 'off';
1074
+
1075
+ const CLEANUP_RANK: Record<CleanupMode, number> = { off: 0, notify: 1, auto: 2 };
1076
+
1077
+ function cleanupValue(doc: unknown): CleanupMode | undefined {
1078
+ const section = doc !== null && typeof doc === 'object' && !Array.isArray(doc) ? (doc as Record<string, unknown>)['worktrees'] : undefined;
1079
+ if (section === null || typeof section !== 'object' || Array.isArray(section)) return undefined;
1080
+ const v = (section as Record<string, unknown>)['cleanup'];
1081
+ if (v === 'auto' || v === 'notify' || v === 'off') return v;
1082
+ // An unquoted `off` is YAML's boolean false.
1083
+ return v === false ? 'off' : undefined;
1084
+ }
1085
+
1086
+ /**
1087
+ * `worktrees.cleanup`. Absent resolves to `notify` (council 2026-10-21 Q2:
1088
+ * installation alone is not consent to delete). The consent to `auto` is the
1089
+ * user's, so only the user-global layers can grant it, read by hand as
1090
+ * `readUpdateMode` reads `update.mode`; a project layer — which a cloned
1091
+ * repository can carry — may lower the mode but never raise it. Fail-closed: a
1092
+ * malformed settings layer reads as `off`, so a file the user broke never lets
1093
+ * the shipped default speak for it.
1094
+ */
1095
+ export function cleanupMode(root: string, opts: { userGlobalPath?: string | null } = {}): CleanupMode {
1096
+ const ug = opts.userGlobalPath ?? null;
1097
+ const scope = { cwd: root, ...(ug !== null ? { user_global_path: ug } : {}) };
1098
+ try {
1099
+ if (settings_layer_states(scope).some((l) => l.state === 'malformed')) return 'off';
1100
+ let user: CleanupMode = 'notify';
1101
+ for (const p of ug !== null ? [ug] : user_global_settings_paths()) {
1102
+ if (!fs.existsSync(p)) continue;
1103
+ user = cleanupValue(parseYaml(fs.readFileSync(p, 'utf-8'), { version: '1.1' })) ?? user;
1104
+ }
1105
+ const none = path.join(root, '.agent-settings-none', 'absent.yml');
1106
+ const project = cleanupValue(load_agent_settings({ cwd: root, user_global_path: none, template_path: none }));
1107
+ return project !== undefined && CLEANUP_RANK[project] < CLEANUP_RANK[user] ? project : user;
1108
+ } catch {
1109
+ return 'off';
1110
+ }
1111
+ }
1112
+
1113
+ /** The daily pass's budget — the retro's, on the same slot (council 2026-10-21 Q1). */
1114
+ export const DAILY_BUDGET_MS = 3000;
1115
+ /** Most recent PRs the daily pass reads; older merges fall back to the tree proof. */
1116
+ export const DAILY_PR_WINDOW = 200;
1117
+ /** Per-candidate record of the last daily pass, in the common git dir. */
1118
+ export const DAILY_RECORD = 'agent-config-worktree-daily.json';
1119
+
1120
+ export interface DailyResult {
1121
+ mode: CleanupMode;
1122
+ scanned: number;
1123
+ total: number;
1124
+ removable: number;
1125
+ removed: number;
1126
+ decide: number;
1127
+ line: string | null;
1128
+ }
1129
+
1130
+ /**
1131
+ * The once-a-day pass (worktrees roadmap 3.3). Synchronous: classification is
1132
+ * bounded by DAILY_BUDGET_MS as a SUBPROCESS deadline; under `auto` at most
1133
+ * DAILY_REMOVAL_CAP removals follow, each re-checked within RECHECK_BUDGET_MS
1134
+ * and removed within REMOVAL_TIMEOUT_MS. Run on the first session of the
1135
+ * day by the existing `session_start` handler. Declared as an authority
1136
+ * expansion: under `worktrees.cleanup: auto` it deletes worktrees, which is
1137
+ * acting, not observing — the user-owned key is what authorises it (ADR-295).
1138
+ * Under `notify` it removes nothing and says how many it could.
1139
+ *
1140
+ * Fair across days: the traversal starts at a different worktree each day, so
1141
+ * a repository whose first few candidates are slow still has every candidate
1142
+ * reached within a few passes. A pass the budget cut short reports how far it
1143
+ * got and is still stamped — tomorrow's start point is different anyway.
1144
+ */
1145
+ export function dailyCleanup(
1146
+ root: string,
1147
+ deps: {
1148
+ now?: Date;
1149
+ mode?: CleanupMode;
1150
+ run?: GhRunner;
1151
+ budgetMs?: number;
1152
+ ranToday?: (root: string) => boolean;
1153
+ stamp?: (root: string) => void;
1154
+ } = {},
1155
+ ): DailyResult | null {
1156
+ const now = deps.now ?? new Date();
1157
+ try {
1158
+ const mode = deps.mode ?? cleanupMode(root);
1159
+ if (mode === 'off') return null;
1160
+ if (deps.ranToday?.(root) === true) return null;
1161
+ const deadlineAt = Date.now() + (deps.budgetMs ?? DAILY_BUDGET_MS);
1162
+ const classified = withDeadline(deadlineAt, () => {
1163
+ const entries = listWorktrees(root);
1164
+ const mainPath = canonical(entries.length > 0 ? entries[0]!.path : root);
1165
+ const here = canonical(root);
1166
+ const candidates = entries.slice(1).filter((e) => {
1167
+ const t = canonical(e.path);
1168
+ return here !== t && !here.startsWith(t + path.sep);
1169
+ });
1170
+ const day = Math.floor(now.getTime() / 86400000);
1171
+ const start = candidates.length === 0 ? 0 : day % candidates.length;
1172
+ const ordered = [...candidates.slice(start), ...candidates.slice(0, start)];
1173
+
1174
+ const selfSessionId = process.env['CLAUDE_CODE_SESSION_ID'] ?? null;
1175
+ const sessionPaths = liveSessionPaths(mainPath, now, selfSessionId);
1176
+ const ctx: ClassifyContext = {
1177
+ readSessions: true,
1178
+ selfSessionId,
1179
+ trunk: resolveTrunk(mainPath),
1180
+ mainPath,
1181
+ now,
1182
+ liveCutoff: now.getTime() - LIVE_WINDOW_HOURS * 3600 * 1000,
1183
+ sessionPaths,
1184
+ registry: readRegistry(mainPath),
1185
+ ageCutoff: null,
1186
+ minAgeDays: null,
1187
+ forge: {
1188
+ // 200 PRs read in ~1.2 s on this repository (measured 2026-10-21; 1,000 took 6.1 s),
1189
+ // which leaves the rest of the three seconds for the candidates.
1190
+ prIndex: readPrIndex(mainPath, { limit: DAILY_PR_WINDOW, ...(deps.run === undefined ? {} : { run: deps.run }) }),
1191
+ mergeDelayHours: MERGE_DELAY_HOURS,
1192
+ },
1193
+ };
1194
+ const rows: InventoryRow[] = [];
1195
+ for (const e of ordered) {
1196
+ if (Date.now() >= deadlineAt) break;
1197
+ try {
1198
+ rows.push(classifyEntry(e, ctx));
1199
+ } catch {
1200
+ break; // the deadline cut a git call short: fail closed, keep the rest
1201
+ }
1202
+ }
1203
+ const inv: Inventory = {
1204
+ trunk: ctx.trunk,
1205
+ rows,
1206
+ context: ctx,
1207
+ counts: { total: rows.length, safe: 0, review: 0, live: 0, reviewReasons: {} },
1208
+ };
1209
+ const safe = rows.filter((r) => r.classification === 'safe');
1210
+ return { inv, safe, rows, candidates, ctx };
1211
+ });
1212
+ let outcomes: RemovalOutcome[] = [];
1213
+ if (mode === 'auto' && classified.safe.length > 0) {
1214
+ try {
1215
+ // Every git call of the removal phase is bounded too: the per-tree
1216
+ // re-check and the removal set their own, tighter limits inside.
1217
+ const removalBudget = DAILY_REMOVAL_CAP * (RECHECK_BUDGET_MS + REMOVAL_TIMEOUT_MS) + DAILY_BUDGET_MS;
1218
+ outcomes = withDeadline(Date.now() + removalBudget, () =>
1219
+ applyRemovals(classified.ctx.mainPath, classified.inv, { now, limit: DAILY_REMOVAL_CAP, here: root }),
1220
+ );
1221
+ } catch {
1222
+ outcomes = [];
1223
+ }
1224
+ }
1225
+ const result = (() => {
1226
+ const { inv, safe, rows, candidates, ctx } = classified;
1227
+ const removed = outcomes.filter((o) => o.removed).length;
1228
+ const decide = rows.filter((r) => r.classification === 'review').length;
1229
+ const dir = withDeadline(Date.now() + DAILY_BUDGET_MS, () => commonDir(ctx.mainPath));
1230
+ if (dir !== null) {
1231
+ const record = {
1232
+ at: now.toISOString(),
1233
+ mode,
1234
+ scanned: rows.length,
1235
+ total: candidates.length,
1236
+ rows: rows.map((r) => ({ path: r.path, branch: r.branch, classification: r.classification, evidence: r.mergeEvidence, reasons: r.reasons })),
1237
+ outcomes,
1238
+ };
1239
+ fs.writeFileSync(path.join(dir, DAILY_RECORD), `${JSON.stringify(record, null, 2)}\n`);
1240
+ }
1241
+ const cut = rows.length < candidates.length ? ` (${rows.length}/${candidates.length} checked today)` : '';
1242
+ let line: string | null = null;
1243
+ if (mode === 'auto' && (removed > 0 || decide > 0)) {
1244
+ line = `${removalSummary(inv, outcomes, { names: false })}${cut}`;
1245
+ } else if (mode === 'notify' && safe.length > 0) {
1246
+ line =
1247
+ `worktrees: ${safe.length} merged, clean and unused — remove with /worktree cleanup --apply, ` +
1248
+ `or set worktrees.cleanup: auto${cut}`;
1249
+ }
1250
+ return { mode, scanned: rows.length, total: candidates.length, removable: safe.length, removed, decide, line };
1251
+ })();
1252
+ deps.stamp?.(root);
1253
+ return result;
1254
+ } catch {
1255
+ // A pass that failed is still today's pass: without the stamp it would
1256
+ // rerun on every session start of the day.
1257
+ try {
1258
+ deps.stamp?.(root);
1259
+ } catch {
1260
+ /* an unwritable stamp is the caller's to report */
1261
+ }
1262
+ return null;
1263
+ }
1264
+ }
1265
+
547
1266
  function usage(): never {
548
1267
  process.stderr.write(
549
1268
  'usage: worktree_cleanup_check check <worktree-path> | scope-overlap [repo-path] | ' +
550
- 'inventory [repo-path] [--json|--plan] [--min-age-days=N] [--exclude-live-sessions]\n',
1269
+ 'inventory [repo-path] [--json|--plan] [--min-age-days=N] [--exclude-live-sessions] [--offline] [--trunk=<ref>] | ' +
1270
+ 'apply [repo-path] [--branch=<name>] [--no-delay] [--offline] [--json] [--respect-setting] [--trunk=<ref>] | ' +
1271
+ 'register <worktree-path> [--purpose=<text>]\n',
551
1272
  );
552
1273
  process.exit(2);
553
1274
  }
@@ -587,15 +1308,77 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
587
1308
  }
588
1309
  return 1;
589
1310
  }
1311
+ if (mode === 'register') {
1312
+ const p = argv[1];
1313
+ if (p === undefined || p.startsWith('--')) usage();
1314
+ const purposeFlag = argv.slice(2).find((a) => a.startsWith('--purpose='));
1315
+ const purpose = purposeFlag === undefined ? 'unspecified' : purposeFlag.slice('--purpose='.length);
1316
+ const e = registerWorktree(path.resolve(p), path.resolve(p), purpose);
1317
+ process.stdout.write(`registered ${e.path} (${e.branch ?? 'detached'}, ${e.purpose})\n`);
1318
+ return 0;
1319
+ }
1320
+ if (mode === 'apply') {
1321
+ const rest = argv.slice(1);
1322
+ const flags = rest.filter((a) => a.startsWith('--'));
1323
+ const positional = rest.filter((a) => !a.startsWith('--'));
1324
+ const KNOWN_APPLY = ['--no-delay', '--offline', '--json', '--respect-setting'];
1325
+ const trunkFlag = flags.find((f) => f.startsWith('--trunk='));
1326
+ const branchFlag = flags.find((f) => f.startsWith('--branch='));
1327
+ if (
1328
+ positional.length > 1 ||
1329
+ flags.some((f) => !KNOWN_APPLY.includes(f) && !f.startsWith('--branch=') && !f.startsWith('--trunk='))
1330
+ ) {
1331
+ usage();
1332
+ }
1333
+ const repo = path.resolve(positional[0] ?? '.');
1334
+ // `--respect-setting`: the path a merge takes on its own initiative
1335
+ // (`/pr:merge`). It removes only under `worktrees.cleanup: auto`; the
1336
+ // explicit `/worktree cleanup --apply` is the user's own ask and does not
1337
+ // consult the key (ADR-295).
1338
+ if (flags.includes('--respect-setting')) {
1339
+ const mode = cleanupMode(repo);
1340
+ if (mode !== 'auto') {
1341
+ if (mode === 'notify') {
1342
+ process.stdout.write(
1343
+ 'worktrees: not removed — worktrees.cleanup is notify; /worktree cleanup --apply removes the merged ones\n',
1344
+ );
1345
+ }
1346
+ return 0;
1347
+ }
1348
+ }
1349
+ const onlyBranch = branchFlag === undefined ? null : branchFlag.slice('--branch='.length);
1350
+ const inv = buildInventory(repo, {
1351
+ excludeLiveSessions: true,
1352
+ selfSessionId: process.env['CLAUDE_CODE_SESSION_ID'] ?? null,
1353
+ // `/pr:merge`'s own tree: its fresh mtimes are the merge, not a second session.
1354
+ mergedBranch: flags.includes('--no-delay') ? onlyBranch : null,
1355
+ prIndex: flags.includes('--offline') ? null : readPrIndex(repo),
1356
+ mergeDelayHours: flags.includes('--no-delay') ? 0 : MERGE_DELAY_HOURS,
1357
+ ...(trunkFlag === undefined ? {} : { trunk: trunkFlag.slice('--trunk='.length) }),
1358
+ });
1359
+ const outcomes = applyRemovals(repo, inv, { onlyBranch });
1360
+ if (flags.includes('--json')) {
1361
+ process.stdout.write(`${JSON.stringify({ outcomes, counts: inv.counts }, null, 2)}\n`);
1362
+ } else {
1363
+ for (const o of outcomes) {
1364
+ process.stdout.write(
1365
+ o.removed ? `removed ${o.path} (${o.evidence ?? 'merged'})\n` : `refused ${o.path}: ${o.error}\n`,
1366
+ );
1367
+ }
1368
+ process.stdout.write(`${removalSummary(inv, outcomes)}\n`);
1369
+ }
1370
+ return outcomes.some((o) => !o.removed) ? 1 : 0;
1371
+ }
590
1372
  if (mode === 'inventory') {
591
1373
  const rest = argv.slice(1);
592
1374
  const flags = rest.filter((a) => a.startsWith('--'));
593
1375
  const positional = rest.filter((a) => !a.startsWith('--'));
594
- const KNOWN = ['--json', '--plan', '--exclude-live-sessions'];
1376
+ const KNOWN = ['--json', '--plan', '--exclude-live-sessions', '--offline'];
1377
+ const invTrunk = flags.find((f) => f.startsWith('--trunk='));
595
1378
  const ageFlag = flags.find((f) => f.startsWith('--min-age-days='));
596
1379
  if (
597
1380
  positional.length > 1 ||
598
- flags.some((f) => !KNOWN.includes(f) && !f.startsWith('--min-age-days='))
1381
+ flags.some((f) => !KNOWN.includes(f) && !f.startsWith('--min-age-days=') && !f.startsWith('--trunk='))
599
1382
  ) {
600
1383
  usage();
601
1384
  }
@@ -616,10 +1399,13 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
616
1399
  const inv = buildInventory(repo, {
617
1400
  minAgeDays,
618
1401
  excludeLiveSessions: flags.includes('--exclude-live-sessions'),
1402
+ prIndex: flags.includes('--offline') ? null : readPrIndex(repo),
1403
+ ...(invTrunk === undefined ? {} : { trunk: invTrunk.slice('--trunk='.length) }),
619
1404
  });
620
1405
 
621
1406
  if (flags.includes('--json')) {
622
- process.stdout.write(`${JSON.stringify(inv, null, 2)}\n`);
1407
+ const { context: _ctx, ...plain } = inv;
1408
+ process.stdout.write(`${JSON.stringify(plain, null, 2)}\n`);
623
1409
  return 0;
624
1410
  }
625
1411
  if (flags.includes('--plan')) {
@@ -630,8 +1416,8 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
630
1416
  }
631
1417
  process.stdout.write(
632
1418
  `# Prepared removal plan for ${plan.length} safe worktree(s).\n` +
633
- '# NOT executed: bulk worktree + branch deletion is a Hard-Floor action that\n' +
634
- '# needs the maintainer\'s explicit approval. Review, then run deliberately.\n',
1419
+ '# NOT executed here. `apply` removes the safe set itself (worktrees only,\n' +
1420
+ '# never --force); the `branch -d` lines stay yours to run.\n',
635
1421
  );
636
1422
  process.stdout.write(`${plan.join('\n')}\n`);
637
1423
  return 0;
@@ -652,14 +1438,20 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
652
1438
  }
653
1439
  process.stdout.write(
654
1440
  '\nThis mode reports only. `--plan` prints the removal commands for the safe set;\n' +
655
- 'running them is a Hard-Floor action needing the maintainer\'s explicit approval.\n',
1441
+ '`apply` removes that set (proven merged, clean, not live), and nothing else.\n',
656
1442
  );
657
1443
  return 0;
658
1444
  }
659
1445
  usage();
660
1446
  }
661
1447
 
1448
+ // Bundle-safety: this module is inlined into the hook bundle (the daily pass),
1449
+ // where every module shares the bundle's `import.meta.url` — so the argv match
1450
+ // below would be true inside every hook and `main()` would exit the dispatcher.
1451
+ declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
1452
+
662
1453
  function _isCliEntry(): boolean {
1454
+ if (typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__) return false;
663
1455
  if (process.argv[1] === undefined) return false;
664
1456
  const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
665
1457
  if (import.meta.url === argvUrl) return true;
@@ -673,7 +1465,9 @@ function _isCliEntry(): boolean {
673
1465
  }
674
1466
  }
675
1467
 
676
- if (_isCliEntry()) {
1468
+ // The `typeof` test is folded by the bundler, so inside the hook bundle the CLI
1469
+ // (`main` and what only it reaches) is dead code and dropped, not merely unrun.
1470
+ if (typeof __AGENT_CONFIG_BUNDLE__ === 'undefined' && _isCliEntry()) {
677
1471
  try {
678
1472
  process.exit(main());
679
1473
  } catch (e) {