mandrel 1.94.0 → 2.1.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 (560) hide show
  1. package/.agents/README.md +116 -99
  2. package/.agents/agents/acceptance-critic.md +9 -7
  3. package/.agents/agents/story-worker.md +45 -51
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +498 -1287
  6. package/.agents/docs/agentrc-reference.json +185 -80
  7. package/.agents/docs/configuration.md +132 -190
  8. package/.agents/docs/execution-reference.md +51 -25
  9. package/.agents/docs/quality-gates.md +25 -33
  10. package/.agents/docs/workflows.md +8 -8
  11. package/.agents/instructions.md +113 -139
  12. package/.agents/rules/ci-remediation.md +11 -15
  13. package/.agents/rules/git-conventions-reference.md +48 -58
  14. package/.agents/rules/git-conventions.md +16 -22
  15. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  16. package/.agents/schemas/agentrc.schema.json +83 -254
  17. package/.agents/schemas/audit-rules.json +59 -1
  18. package/.agents/schemas/audit-rules.schema.json +33 -1
  19. package/.agents/schemas/lifecycle/README.md +1 -2
  20. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  21. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  22. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  23. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  24. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  25. package/.agents/schemas/signal-event.schema.json +3 -3
  26. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  27. package/.agents/schemas/validation-evidence.schema.json +1 -1
  28. package/.agents/scripts/acceptance-eval.js +22 -66
  29. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  30. package/.agents/scripts/audit-to-stories.js +7 -7
  31. package/.agents/scripts/boot-sweep.js +1 -1
  32. package/.agents/scripts/bootstrap.js +3 -3
  33. package/.agents/scripts/check-dead-exports.js +43 -104
  34. package/.agents/scripts/check-doc-links.js +2 -2
  35. package/.agents/scripts/check-lifecycle-lint.js +7 -10
  36. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  37. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  38. package/.agents/scripts/deliver-recover.js +122 -0
  39. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  40. package/.agents/scripts/evidence-gate.js +20 -50
  41. package/.agents/scripts/generate-skills-index.js +17 -1
  42. package/.agents/scripts/generate-workflows-doc.js +4 -4
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  44. package/.agents/scripts/lib/Logger.js +6 -10
  45. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  46. package/.agents/scripts/lib/audit-suite/selector.js +328 -28
  47. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  48. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  49. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -15
  50. package/.agents/scripts/lib/baselines/reader.js +1 -6
  51. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  52. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  53. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  54. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  55. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  56. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  57. package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
  58. package/.agents/scripts/lib/checks/index.js +3 -2
  59. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  60. package/.agents/scripts/lib/checks/state.js +17 -248
  61. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
  62. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  63. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  64. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  65. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  66. package/.agents/scripts/lib/cli-args.js +39 -9
  67. package/.agents/scripts/lib/close-validation/gates.js +15 -15
  68. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  69. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  70. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  71. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  72. package/.agents/scripts/lib/config/ci.js +6 -31
  73. package/.agents/scripts/lib/config/delivery-routing.js +52 -35
  74. package/.agents/scripts/lib/config/explain.js +61 -48
  75. package/.agents/scripts/lib/config/github.js +7 -5
  76. package/.agents/scripts/lib/config/limits.js +29 -80
  77. package/.agents/scripts/lib/config/paths.js +0 -2
  78. package/.agents/scripts/lib/config/quality.js +12 -15
  79. package/.agents/scripts/lib/config/runners.js +20 -66
  80. package/.agents/scripts/lib/config/temp-paths.js +30 -63
  81. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  82. package/.agents/scripts/lib/config-resolver.js +2 -7
  83. package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
  84. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
  85. package/.agents/scripts/lib/config-settings-schema.js +100 -60
  86. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  87. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  88. package/.agents/scripts/lib/dependency-parser.js +3 -2
  89. package/.agents/scripts/lib/doc-tiers.js +2 -2
  90. package/.agents/scripts/lib/duplicate-search.js +242 -41
  91. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  92. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  93. package/.agents/scripts/lib/format-generated-json.js +97 -0
  94. package/.agents/scripts/lib/framework-version.js +19 -190
  95. package/.agents/scripts/lib/gh-exec.js +8 -0
  96. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  97. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
  98. package/.agents/scripts/lib/git-utils.js +32 -20
  99. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  100. package/.agents/scripts/lib/json-utils.js +1 -2
  101. package/.agents/scripts/lib/label-constants.js +10 -38
  102. package/.agents/scripts/lib/label-taxonomy.js +10 -55
  103. package/.agents/scripts/lib/observability/active-story-env.js +44 -165
  104. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  105. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  106. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  107. package/.agents/scripts/lib/observability/source-classifier.js +5 -5
  108. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  109. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  110. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  111. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  112. package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
  113. package/.agents/scripts/lib/orchestration/code-review.js +78 -436
  114. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  115. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
  116. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  117. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  118. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  119. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  120. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  121. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  122. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  123. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  124. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  125. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
  126. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  127. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  128. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  129. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
  130. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  131. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  132. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  133. package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
  134. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  135. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  136. package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
  137. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
  138. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
  139. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  140. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  141. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
  142. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
  143. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  144. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
  145. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
  146. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
  147. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  148. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  149. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  150. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +52 -51
  151. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  152. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
  153. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  154. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  155. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  156. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  157. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  158. package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
  159. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  160. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  161. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  162. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  163. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  164. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  165. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  166. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  167. package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
  168. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
  169. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  170. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  171. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
  172. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  173. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
  174. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  175. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  176. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
  177. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  178. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  179. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
  180. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  181. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  182. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  183. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  184. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  185. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  186. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  187. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
  188. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  189. package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
  190. package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
  191. package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
  192. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  193. package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
  194. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  195. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
  196. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
  197. package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
  198. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
  199. package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
  200. package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
  201. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  202. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  203. package/.agents/scripts/lib/planning-corpus.js +12 -281
  204. package/.agents/scripts/lib/preflight-runner.js +4 -4
  205. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  206. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  207. package/.agents/scripts/lib/signals/index.js +4 -17
  208. package/.agents/scripts/lib/signals/read.js +35 -35
  209. package/.agents/scripts/lib/signals/schema.js +8 -11
  210. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  211. package/.agents/scripts/lib/signals/write.js +0 -1
  212. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  213. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  214. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  215. package/.agents/scripts/lib/story-adjacency.js +17 -19
  216. package/.agents/scripts/lib/story-body/story-body.js +130 -75
  217. package/.agents/scripts/lib/story-plan.js +2 -4
  218. package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
  219. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  220. package/.agents/scripts/lib/test-env.js +14 -1
  221. package/.agents/scripts/lib/test-tiers.js +0 -3
  222. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
  223. package/.agents/scripts/lib/validation-evidence.js +32 -60
  224. package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
  225. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  226. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  227. package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
  228. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  229. package/.agents/scripts/lint-issue-body.js +71 -40
  230. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  231. package/.agents/scripts/notify.js +4 -3
  232. package/.agents/scripts/plan-context.js +102 -80
  233. package/.agents/scripts/plan-persist.js +230 -279
  234. package/.agents/scripts/plan-run-epilogue.js +142 -0
  235. package/.agents/scripts/post-structured-comment.js +0 -38
  236. package/.agents/scripts/pr-watch-with-update.js +43 -22
  237. package/.agents/scripts/providers/github/compose.js +0 -1
  238. package/.agents/scripts/providers/github/errors.js +0 -19
  239. package/.agents/scripts/providers/github/issues.js +13 -39
  240. package/.agents/scripts/providers/github/mappers.js +5 -12
  241. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  242. package/.agents/scripts/providers/github/tickets.js +33 -156
  243. package/.agents/scripts/providers/github.js +17 -6
  244. package/.agents/scripts/resolve-stories.js +236 -0
  245. package/.agents/scripts/run-coverage.js +4 -1
  246. package/.agents/scripts/run-lint.js +2 -2
  247. package/.agents/scripts/run-verify.js +31 -2
  248. package/.agents/scripts/signals-view.js +25 -21
  249. package/.agents/scripts/single-story-close.js +178 -26
  250. package/.agents/scripts/single-story-confirm-merge.js +313 -24
  251. package/.agents/scripts/single-story-init.js +35 -30
  252. package/.agents/scripts/stories-wave-tick.js +85 -10
  253. package/.agents/scripts/story-plan.js +28 -49
  254. package/.agents/scripts/update-ticket-state.js +14 -65
  255. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  256. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  257. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  258. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  259. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  260. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  261. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  262. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  263. package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
  264. package/.agents/skills/core/scope-triage/SKILL.md +31 -172
  265. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  266. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  267. package/.agents/skills/skills.index.json +3 -53
  268. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  269. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  270. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  271. package/.agents/starter-agentrc.json +0 -5
  272. package/.agents/templates/agent-protocol.md +9 -10
  273. package/.agents/workflows/audit-architecture.md +6 -7
  274. package/.agents/workflows/audit-clean-code.md +7 -7
  275. package/.agents/workflows/audit-dependencies.md +3 -3
  276. package/.agents/workflows/audit-devops.md +3 -3
  277. package/.agents/workflows/audit-documentation.md +9 -10
  278. package/.agents/workflows/audit-lighthouse.md +11 -3
  279. package/.agents/workflows/audit-navigability.md +13 -2
  280. package/.agents/workflows/audit-performance.md +5 -6
  281. package/.agents/workflows/audit-privacy.md +3 -3
  282. package/.agents/workflows/audit-quality.md +11 -12
  283. package/.agents/workflows/audit-security.md +4 -5
  284. package/.agents/workflows/audit-seo.md +13 -3
  285. package/.agents/workflows/audit-sre.md +3 -3
  286. package/.agents/workflows/audit-to-stories.md +20 -20
  287. package/.agents/workflows/audit-ux-ui.md +10 -3
  288. package/.agents/workflows/deliver.md +177 -176
  289. package/.agents/workflows/git-cleanup.md +5 -6
  290. package/.agents/workflows/git-deliver.md +1 -1
  291. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  292. package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
  293. package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
  294. package/.agents/workflows/helpers/code-review.md +75 -196
  295. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
  296. package/.agents/workflows/helpers/deliver-story.md +606 -0
  297. package/.agents/workflows/helpers/diagnose.md +10 -10
  298. package/.agents/workflows/helpers/parallel-tooling.md +3 -3
  299. package/.agents/workflows/helpers/signals.md +16 -16
  300. package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
  301. package/.agents/workflows/mandrel-update.md +2 -1
  302. package/.agents/workflows/plan.md +277 -145
  303. package/.agents/workflows/qa-assist.md +27 -33
  304. package/.agents/workflows/qa-explore.md +29 -38
  305. package/.agents/workflows/qa-run.md +2 -6
  306. package/README.md +9 -8
  307. package/bin/mandrel.js +12 -1
  308. package/docs/CHANGELOG.md +70 -0
  309. package/lib/cli/registry.js +262 -19
  310. package/lib/cli/sync-agents.js +157 -0
  311. package/lib/cli/sync-commands.js +115 -6
  312. package/lib/cli/sync.js +168 -6
  313. package/lib/cli/update.js +105 -8
  314. package/lib/cli/version-helpers.js +131 -0
  315. package/lib/migrations/README.md +7 -5
  316. package/lib/migrations/index.js +12 -8
  317. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  318. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  319. package/package.json +2 -2
  320. package/.agents/agents/retro.md +0 -42
  321. package/.agents/personas/architect.md +0 -113
  322. package/.agents/personas/devops-engineer.md +0 -38
  323. package/.agents/personas/engineer.md +0 -33
  324. package/.agents/personas/project-manager.md +0 -114
  325. package/.agents/personas/qa-engineer.md +0 -95
  326. package/.agents/personas/security-engineer.md +0 -111
  327. package/.agents/personas/technical-writer.md +0 -101
  328. package/.agents/schemas/dispatch-manifest.json +0 -232
  329. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  330. package/.agents/schemas/epic-spec.schema.json +0 -153
  331. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  332. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  333. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  334. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  335. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  336. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  337. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  338. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  339. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  340. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  341. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  342. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  343. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  344. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  345. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  346. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  347. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  348. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  349. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  350. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  351. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  352. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  353. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  354. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  355. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  356. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  357. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  358. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  359. package/.agents/schemas/risk-verdict.schema.json +0 -66
  360. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  361. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  362. package/.agents/scripts/analyze-execution.js +0 -444
  363. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  364. package/.agents/scripts/check-prepush-recovery.js +0 -90
  365. package/.agents/scripts/dispatcher.js +0 -295
  366. package/.agents/scripts/epic-audit-prepare.js +0 -497
  367. package/.agents/scripts/epic-audit-recheck.js +0 -274
  368. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  369. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  370. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  371. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  372. package/.agents/scripts/epic-plan-clarity.js +0 -211
  373. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  374. package/.agents/scripts/epic-reconcile.js +0 -625
  375. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  376. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  377. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  378. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  379. package/.agents/scripts/lib/config/preflight.js +0 -58
  380. package/.agents/scripts/lib/config/retro.js +0 -77
  381. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  382. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  383. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  384. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  385. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  386. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
  387. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  388. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  389. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  390. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
  391. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  392. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  393. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  394. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  395. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  396. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  397. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  398. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  399. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  400. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  401. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  402. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  403. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  404. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  405. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  406. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  407. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  408. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
  409. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  410. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  411. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  412. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  413. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  414. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  415. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  416. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  417. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  418. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  419. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  420. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  421. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  422. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  423. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  424. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  425. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  426. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
  427. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  428. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  429. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  430. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  431. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  432. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  433. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  434. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  435. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  436. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  437. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  438. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  439. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  440. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  441. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  442. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  443. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  444. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  445. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  446. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  447. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  448. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  449. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  450. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  451. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  452. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  453. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  454. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  455. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  456. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  457. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  458. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  459. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  460. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  461. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
  462. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  463. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  464. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  465. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
  466. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  467. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  468. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  469. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  470. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  471. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  472. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  473. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  474. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  475. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  476. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  477. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  478. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  479. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  480. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  481. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  482. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  483. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  484. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  485. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  486. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  487. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  488. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  489. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  490. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  491. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  492. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  493. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  494. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  495. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  496. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  497. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  498. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  499. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  500. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  501. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  502. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  503. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  504. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  505. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  506. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  507. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  508. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  509. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  510. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  511. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  512. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  513. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  514. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  515. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  516. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  517. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  518. package/.agents/scripts/lib/spec/index.js +0 -36
  519. package/.agents/scripts/lib/spec/loader.js +0 -425
  520. package/.agents/scripts/lib/spec/state.js +0 -208
  521. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  522. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  523. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  524. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  525. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  526. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  527. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  528. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  529. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  530. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  531. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  532. package/.agents/scripts/lifecycle-emit.js +0 -510
  533. package/.agents/scripts/retro-run.js +0 -218
  534. package/.agents/scripts/slice-phase.js +0 -361
  535. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  536. package/.agents/scripts/story-close.js +0 -294
  537. package/.agents/scripts/story-init.js +0 -599
  538. package/.agents/scripts/story-phase.js +0 -369
  539. package/.agents/scripts/wave-tick.js +0 -464
  540. package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
  541. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  542. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  543. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  544. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  545. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  546. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  547. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  548. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  549. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  550. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  551. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  552. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  553. package/.agents/workflows/helpers/epic-audit.md +0 -189
  554. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  555. package/.agents/workflows/helpers/epic-testing.md +0 -125
  556. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  557. package/.agents/workflows/helpers/plan-epic.md +0 -353
  558. package/.agents/workflows/helpers/plan-story.md +0 -251
  559. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  560. package/.agents/workflows/helpers/single-story-deliver.md +0 -557
@@ -6,16 +6,19 @@
6
6
  * without importing upward from a top-level CLI file.
7
7
  *
8
8
  * Pure (modulo `gitSpawn`) — exposed helpers are:
9
- * - matchesFilePattern — single file × single glob (picomatch with `dot`)
10
- * - matchesAnyFilePattern — file list × pattern list, short-circuiting
11
- * - selectAudits main entry; reads audit-rules.json, runs `git
12
- * diff --name-only`, applies keyword + glob rules.
9
+ * - matchesFilePattern — single file × single glob (picomatch, `dot`)
10
+ * - matchesAnyFilePattern — file list × pattern list, short-circuiting
11
+ * - selectSensitivePathClasses change set × the manifest's `sensitivePaths`
12
+ * block; the review-depth derivation's matcher
13
+ * - selectAudits — main entry; reads audit-rules.json, runs `git
14
+ * diff --name-only`, applies keyword + glob
15
+ * rules.
13
16
  *
14
17
  * All rule-matching lives here; the former `select-audits.js` CLI wrapper
15
18
  * was retired in #4482 (consumers call `selectAudits` via the barrel).
16
19
  */
17
20
 
18
- import { readFileSync } from 'node:fs';
21
+ import { readdirSync, readFileSync } from 'node:fs';
19
22
  import fs from 'node:fs/promises';
20
23
  import path from 'node:path';
21
24
  import picomatch from 'picomatch';
@@ -109,10 +112,10 @@ export const LENS_TIERS = Object.freeze(['local', 'cumulative', 'global']);
109
112
  * @throws {Error} When the manifest cannot be read or parsed.
110
113
  */
111
114
  function readAuditRulesSync() {
112
- const { agentSettings } = resolveConfig();
115
+ const config = resolveConfig();
113
116
  const rulesPath = path.join(
114
117
  PROJECT_ROOT,
115
- getPaths({ agentSettings }).schemasRoot,
118
+ getPaths(config).schemasRoot,
116
119
  'audit-rules.json',
117
120
  );
118
121
  try {
@@ -160,7 +163,7 @@ export function resolveLensTier(lens) {
160
163
  * every path) matches every change set here, so its concern is verified at
161
164
  * BOTH innermost tiers — the
162
165
  * write-time checklist threading and this Story-scope lens pass — and excluded
163
- * from Epic close (a local lens is dropped by {@link selectEpicCloseLenses}).
166
+ * from the retired Epic-close roster (local lenses stay Story-scope only).
164
167
  * A local lens with an empty `filePatterns` list matches nothing here, so a
165
168
  * diff matching no local lens's patterns yields an empty roster and adds no
166
169
  * lens work.
@@ -197,6 +200,50 @@ export function selectLocalLenses({
197
200
  return selected;
198
201
  }
199
202
 
203
+ /**
204
+ * Select the sensitive-path classes a change set touches, from the
205
+ * `sensitivePaths` block of [`audit-rules.json`](../../../schemas/audit-rules.json).
206
+ *
207
+ * This is the matcher behind the close-time review-depth derivation
208
+ * (`review-depth.js#deriveChangeLevel`, Story #4542): a change set intersecting
209
+ * any registered class's globs is *observably* sensitive — auth, a migration, a
210
+ * billing path — and earns a deep pass however narrow the diff is. The classes
211
+ * and their globs live in the manifest next to the lens `triggers.filePatterns`
212
+ * precisely so an operator can extend them without a code change, and matching
213
+ * runs through the same {@link matchesAnyFilePattern} picomatch machinery rather
214
+ * than a second matcher with its own glob semantics.
215
+ *
216
+ * An empty change set, an absent `sensitivePaths` block, or a class whose globs
217
+ * match nothing all contribute no class — the caller then resolves depth from
218
+ * diff width alone.
219
+ *
220
+ * Pure over its injected seam: `injectedRules` skips the manifest disk read.
221
+ * Selection order follows the manifest's declaration order, which is
222
+ * deterministic.
223
+ *
224
+ * @param {{
225
+ * changedFiles?: string[],
226
+ * injectedRules?: { sensitivePaths?: Record<string, { filePatterns?: string[] }> },
227
+ * }} [params]
228
+ * @returns {string[]} The matched class names, in manifest order.
229
+ */
230
+ export function selectSensitivePathClasses({
231
+ changedFiles,
232
+ injectedRules,
233
+ } = {}) {
234
+ const files = Array.isArray(changedFiles) ? changedFiles : [];
235
+ if (files.length === 0) return [];
236
+
237
+ const rules = injectedRules ?? readAuditRulesSync();
238
+ const matched = [];
239
+ for (const [name, entry] of Object.entries(rules.sensitivePaths ?? {})) {
240
+ if (matchesAnyFilePattern(entry?.filePatterns ?? [], files)) {
241
+ matched.push(name);
242
+ }
243
+ }
244
+ return matched;
245
+ }
246
+
200
247
  /**
201
248
  * Resolve the consumer's navigability route globs from the resolved config.
202
249
  * Reads `delivery.quality.navigability.routeGlobs` — the route-tree SSOT the
@@ -221,9 +268,9 @@ export function resolveNavigabilityRouteGlobs(config) {
221
268
  * `false` (the unconfigured no-op), so the existing change-set-scoped lens
222
269
  * selection is unchanged.
223
270
  *
224
- * This is a pure predicate over the SAME inputs the existing risk-routed-lens
225
- * union already consumes; the caller folds its result into `riskRoutedAudits`
226
- * via the existing `unionAudits` no new routing machinery is added.
271
+ * A pure predicate over a change set the same input {@link selectAudits} and
272
+ * {@link selectLocalLenses} already match against. The caller unions its result
273
+ * into the lens roster it is assembling; no new routing machinery is added.
227
274
  *
228
275
  * @param {{ changedFiles?: string[], config?: object|null }} params
229
276
  * @returns {boolean}
@@ -234,6 +281,206 @@ export function routesNavigabilityLens({ changedFiles, config } = {}) {
234
281
  return matchesAnyFilePattern(globs, changedFiles ?? []);
235
282
  }
236
283
 
284
+ /**
285
+ * Package names (or scope/name segments of them) that declare a **web
286
+ * rendering surface**. Matched against the consumer's root `package.json`
287
+ * `dependencies` + `devDependencies` keys, segment-wise, so `@angular/core`
288
+ * matches via `angular` and `@remix-run/react` via `react`.
289
+ */
290
+ const WEB_FRAMEWORK_PACKAGES = Object.freeze([
291
+ 'react',
292
+ 'next',
293
+ 'vue',
294
+ 'svelte',
295
+ 'sveltekit',
296
+ 'astro',
297
+ 'nuxt',
298
+ 'remix',
299
+ 'remix-run',
300
+ 'gatsby',
301
+ 'angular',
302
+ ]);
303
+
304
+ /** File extensions whose presence in the source tree implies a web surface. */
305
+ const WEB_ASSET_EXTENSIONS = Object.freeze(['.html', '.css', '.jsx', '.tsx']);
306
+
307
+ /**
308
+ * Directories the web-surface file scan never descends into. `node_modules` is
309
+ * the load-bearing one (a dependency's bundled `.css` says nothing about the
310
+ * consumer's own surface); the test directories are excluded because a fixture
311
+ * `.html` is a test artifact, not a shipped page.
312
+ */
313
+ const WEB_SCAN_SKIP_DIRS = Object.freeze([
314
+ 'node_modules',
315
+ '.git',
316
+ '.worktrees',
317
+ 'dist',
318
+ 'build',
319
+ 'out',
320
+ 'coverage',
321
+ 'temp',
322
+ 'tmp',
323
+ 'tests',
324
+ 'test',
325
+ '__tests__',
326
+ '__mocks__',
327
+ 'spec',
328
+ 'e2e',
329
+ 'fixtures',
330
+ ]);
331
+
332
+ /** Scan bounds — the probe is a cheap heuristic, not an exhaustive crawl. */
333
+ const WEB_SCAN_MAX_DEPTH = 6;
334
+ const WEB_SCAN_MAX_ENTRIES = 4000;
335
+
336
+ /**
337
+ * Process-lifetime memo for the filesystem half of the web-surface probe,
338
+ * keyed by project root. The config half ({@link resolveNavigabilityRouteGlobs})
339
+ * is a free object read and is deliberately NOT memoized, so a caller passing a
340
+ * different config never reads a stale answer.
341
+ *
342
+ * @type {Map<string, boolean>}
343
+ */
344
+ const _webSurfaceFsCache = new Map();
345
+
346
+ /** Test-only: drop the memo so a fixture root can be re-probed after edits. */
347
+ export function _resetWebSurfaceCache() {
348
+ _webSurfaceFsCache.clear();
349
+ }
350
+
351
+ /**
352
+ * True when the root `package.json` declares a web-framework dependency.
353
+ * Returns `null` — *indeterminate* — when the manifest exists but cannot be
354
+ * read or parsed; the caller fails open on that (see {@link hasWebSurface}).
355
+ * A genuinely absent manifest (`ENOENT`) is determinate: there is no
356
+ * declaration, so there is no signal, and the file scan gets its turn.
357
+ *
358
+ * @param {string} root
359
+ * @returns {boolean|null}
360
+ */
361
+ function declaresWebFramework(root) {
362
+ let raw;
363
+ try {
364
+ raw = readFileSync(path.join(root, 'package.json'), 'utf8');
365
+ } catch (err) {
366
+ if (err?.code === 'ENOENT') return false;
367
+ return null;
368
+ }
369
+ let pkg;
370
+ try {
371
+ pkg = JSON.parse(raw);
372
+ } catch {
373
+ return null;
374
+ }
375
+ const names = [
376
+ ...Object.keys(pkg?.dependencies ?? {}),
377
+ ...Object.keys(pkg?.devDependencies ?? {}),
378
+ ];
379
+ return names.some((name) =>
380
+ name
381
+ .replace(/^@/, '')
382
+ .split('/')
383
+ .some((segment) => WEB_FRAMEWORK_PACKAGES.includes(segment)),
384
+ );
385
+ }
386
+
387
+ /**
388
+ * True when a bounded scan of the source tree finds a web asset file
389
+ * (`.html` / `.css` / `.jsx` / `.tsx`) outside the skipped directories.
390
+ * Returns `null` — *indeterminate* — when the root itself is unreadable, or
391
+ * when the scan exhausted its entry budget without finding one: a truncated
392
+ * scan genuinely did not finish looking, and reporting "no web surface" from
393
+ * a half-walked tree would silently drop lens coverage.
394
+ *
395
+ * Uses `readdirSync(withFileTypes)` rather than `git ls-files` — a filesystem
396
+ * check suffices, and shelling out to git would make the probe cost a process
397
+ * spawn on every selection.
398
+ *
399
+ * @param {string} root
400
+ * @returns {boolean|null}
401
+ */
402
+ function scanForWebAssets(root) {
403
+ let budget = WEB_SCAN_MAX_ENTRIES;
404
+ const queue = [{ dir: root, depth: 0 }];
405
+ let rootRead = false;
406
+
407
+ while (queue.length > 0) {
408
+ const { dir, depth } = queue.shift();
409
+ let entries;
410
+ try {
411
+ entries = readdirSync(dir, { withFileTypes: true });
412
+ } catch {
413
+ // A single unreadable subdirectory is skipped: a permissions oddity is
414
+ // far likelier than an entire web surface hiding behind it. An
415
+ // unreadable ROOT is a different story — see below.
416
+ if (dir === root) return null;
417
+ continue;
418
+ }
419
+ if (dir === root) rootRead = true;
420
+
421
+ for (const entry of entries) {
422
+ if (budget-- <= 0) return null; // truncated ⇒ indeterminate
423
+ if (entry.isDirectory()) {
424
+ if (WEB_SCAN_SKIP_DIRS.includes(entry.name)) continue;
425
+ if (depth + 1 <= WEB_SCAN_MAX_DEPTH) {
426
+ queue.push({ dir: path.join(dir, entry.name), depth: depth + 1 });
427
+ }
428
+ continue;
429
+ }
430
+ if (WEB_ASSET_EXTENSIONS.includes(path.extname(entry.name))) return true;
431
+ }
432
+ }
433
+ return rootRead ? false : null;
434
+ }
435
+
436
+ /**
437
+ * Decide whether the project has a **web surface** — the applicability
438
+ * predicate behind the `target: "web"` gate in `audit-rules.json` (#4579).
439
+ *
440
+ * Mandrel is materialized into other projects, so this cannot be a property of
441
+ * *this* repository: a consumer with a real web surface MUST still get the web
442
+ * lenses. It is therefore derived from observables in the consumer's own
443
+ * checkout, and deliberately NOT from a new `.agentrc` key — a new key would
444
+ * have to be threaded through the runtime AJV (`lib/config-settings-schema*.js`)
445
+ * *and* the published mirror, and would make consumers hand-configure something
446
+ * already derivable.
447
+ *
448
+ * A project is web-capable when ANY of these hold:
449
+ * 1. `delivery.quality.navigability.routeGlobs` is configured — the existing
450
+ * web signal the navigability lens already routes off.
451
+ * 2. The root `package.json` declares a web framework (react / next / vue /
452
+ * svelte / astro / nuxt / remix / gatsby / angular).
453
+ * 3. A bounded source scan finds a `.html` / `.css` / `.jsx` / `.tsx` file
454
+ * outside test directories.
455
+ *
456
+ * **Fail direction: OPEN.** When a signal is indeterminate — an unparseable
457
+ * `package.json`, an unreadable root, a scan that hit its entry budget — the
458
+ * project is treated as web-capable. A false positive costs one wasted lens
459
+ * run; a false negative silently drops audit coverage on a project that has a
460
+ * real web surface, and nothing downstream would ever report the omission.
461
+ * Wasted spend is recoverable; dropped coverage is not.
462
+ *
463
+ * @param {{ config?: object|null, projectRoot?: string }} [params]
464
+ * @returns {boolean}
465
+ */
466
+ export function hasWebSurface({ config, projectRoot = PROJECT_ROOT } = {}) {
467
+ if (resolveNavigabilityRouteGlobs(config).length > 0) return true;
468
+
469
+ if (_webSurfaceFsCache.has(projectRoot)) {
470
+ return _webSurfaceFsCache.get(projectRoot);
471
+ }
472
+
473
+ const declared = declaresWebFramework(projectRoot);
474
+ // `null` is indeterminate, not false — fail open.
475
+ const result =
476
+ declared === null || declared === true
477
+ ? true
478
+ : scanForWebAssets(projectRoot) !== false;
479
+
480
+ _webSurfaceFsCache.set(projectRoot, result);
481
+ return result;
482
+ }
483
+
237
484
  /**
238
485
  * Test a single filename against a single glob pattern using the project's
239
486
  * configured matcher semantics (`picomatch` with `dot: true`). Exported so
@@ -261,6 +508,16 @@ export function matchesAnyFilePattern(patterns, files) {
261
508
  * @param {number} params.ticketId
262
509
  * @param {string} params.gate
263
510
  * @param {import('../ITicketingProvider.js').ITicketingProvider} params.provider
511
+ * @param {string[]} [params.changedFiles]
512
+ * The change set to select over, when the caller already knows it. Supplying
513
+ * it skips the internal `git diff` entirely and `baseBranch` / `headRef` are
514
+ * then unused. Callers whose change set is NOT the working tree's
515
+ * `baseBranch...headRef` MUST pass this: the plan-run epilogue runs from the
516
+ * main checkout *after* its Stories have merged, where any `main...HEAD`
517
+ * range is empty by construction and selection would silently degrade to
518
+ * keyword-only matching (Story #4571). An empty array is honoured as
519
+ * "the set is known, and it is empty" — distinct from omitting the option,
520
+ * which means "derive it from git".
264
521
  * @param {string} [params.baseBranch]
265
522
  * @param {string} [params.headRef]
266
523
  * Git ref whose diff-against-`baseBranch` defines the change set. Defaults
@@ -284,6 +541,9 @@ export function matchesAnyFilePattern(patterns, files) {
284
541
  * Test-only seam to drive the `--gate-mode` / `MANDREL_GATE_MODE=1`
285
542
  * detection; production callers leave unset and `isGateMode` reads
286
543
  * `process.argv` / `process.env`.
544
+ * @param {typeof hasWebSurface} [params.hasWebSurfaceFn]
545
+ * Test-only seam overriding the web-surface probe behind the
546
+ * `target: "web"` applicability gate. Production callers leave unset.
287
547
  *
288
548
  * Returns either the success envelope (`{ selectedAudits, ticketId, gate, context }`)
289
549
  * OR the degraded envelope (`{ ok: false, degraded: true, reason, detail }`)
@@ -294,18 +554,20 @@ export async function selectAudits({
294
554
  ticketId,
295
555
  gate,
296
556
  provider,
557
+ changedFiles: injectedChangedFiles,
297
558
  baseBranch = 'main',
298
559
  headRef = 'HEAD',
299
560
  injectedGitSpawn,
300
561
  gitTimeoutMsOverride,
301
562
  gateModeOpts,
563
+ hasWebSurfaceFn = hasWebSurface,
302
564
  }) {
303
- const { agentSettings } = resolveConfig();
565
+ const config = resolveConfig();
304
566
  const timeoutMs = gitTimeoutMsOverride ?? DEFAULT_GIT_TIMEOUT_MS;
305
567
 
306
568
  const rulesPath = path.join(
307
569
  PROJECT_ROOT,
308
- getPaths({ agentSettings }).schemasRoot,
570
+ getPaths(config).schemasRoot,
309
571
  'audit-rules.json',
310
572
  );
311
573
  let rulesData;
@@ -323,6 +585,14 @@ export async function selectAudits({
323
585
 
324
586
  const runGit = injectedGitSpawn ?? (async (...args) => gitSpawn(...args));
325
587
 
588
+ // A caller that already knows the change set supplies it, and no git ref is
589
+ // consulted at all — `baseBranch` / `headRef` describe a diff that is not
590
+ // being taken. The plan-run epilogue is the motivating caller (Story #4571):
591
+ // it resolves the run's landed diff from the Stories' squash-merges, and any
592
+ // `main...HEAD` range it could name from the main checkout post-land is
593
+ // empty by construction.
594
+ const hasInjectedChangedFiles = Array.isArray(injectedChangedFiles);
595
+
326
596
  // Resolve `headRef` to a commit before diffing. A non-default `headRef`
327
597
  // (Epic-mode callers pass `refs/heads/epic/<id>`) that the repo can't
328
598
  // resolve means the requested Epic's branch is not present in this
@@ -331,7 +601,7 @@ export async function selectAudits({
331
601
  // degraded signal instead of leaking the wrong scope. `HEAD` is always
332
602
  // resolvable in a valid repo, so the default-path callers skip the probe
333
603
  // cost on the common case.
334
- if (headRef !== 'HEAD') {
604
+ if (!hasInjectedChangedFiles && headRef !== 'HEAD') {
335
605
  let resolved;
336
606
  try {
337
607
  resolved = await withTimeout(
@@ -358,18 +628,22 @@ export async function selectAudits({
358
628
  }
359
629
  }
360
630
 
361
- let changedFiles = [];
631
+ let changedFiles = hasInjectedChangedFiles
632
+ ? injectedChangedFiles.map((f) => String(f).trim()).filter(Boolean)
633
+ : [];
362
634
  try {
363
- const diff = await withTimeout(
364
- runGit(
365
- process.cwd(),
366
- 'diff',
367
- '--name-only',
368
- `${baseBranch}...${headRef}`,
369
- ),
370
- timeoutMs,
371
- { label: 'select-audits git diff' },
372
- );
635
+ const diff = hasInjectedChangedFiles
636
+ ? null
637
+ : await withTimeout(
638
+ runGit(
639
+ process.cwd(),
640
+ 'diff',
641
+ '--name-only',
642
+ `${baseBranch}...${headRef}`,
643
+ ),
644
+ timeoutMs,
645
+ { label: 'select-audits git diff' },
646
+ );
373
647
  if (diff?.status === 0) {
374
648
  changedFiles = diff.stdout
375
649
  .split('\n')
@@ -393,16 +667,40 @@ export async function selectAudits({
393
667
 
394
668
  const selectedAudits = [];
395
669
 
670
+ // Resolved at most once per call, and only if a `target: "web"` lens
671
+ // actually clears its gate — a Node-only project must not pay a filesystem
672
+ // scan on a roster with no web lens in it.
673
+ let webSurfaceMemo = null;
674
+ const projectIsWebCapable = () => {
675
+ if (webSurfaceMemo === null) {
676
+ webSurfaceMemo = hasWebSurfaceFn({ config });
677
+ }
678
+ return webSurfaceMemo;
679
+ };
680
+
396
681
  for (const [auditName, ruleOpts] of Object.entries(rulesData.audits || {})) {
397
682
  const triggers = ruleOpts.triggers || {};
398
683
 
399
684
  const gateMatch = triggers.gates?.includes(gate);
400
685
  if (!gateMatch) continue;
401
686
 
687
+ // Target-applicability gate (#4579). A lens declaring `target: "web"`
688
+ // has nothing to read on a project with no web surface, yet still
689
+ // whole-word-matches ordinary prose — `audit-seo` fires on the `meta`
690
+ // inside every Story body's `<!-- meta: {...} -->` machine comment. The
691
+ // roster's own instruction is that the host MUST walk every listed lens,
692
+ // so an inapplicable entry is not just wasted spend: it teaches operators
693
+ // to ignore the MUST. An absent `target` means "always applicable", so no
694
+ // existing lens changes behaviour.
695
+ if (ruleOpts.target === 'web' && !projectIsWebCapable()) continue;
696
+
402
697
  const keywords = triggers.keywords || [];
403
698
  let keywordMatch = false;
404
699
  for (const kw of keywords) {
405
- if (contentToSearch.includes(kw.toLowerCase())) {
700
+ // Whole-word match: a bare substring test selects lenses on accidental
701
+ // fragments ("ui" inside "requires", "auth" inside "author" — #4579).
702
+ const escaped = kw.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
703
+ if (new RegExp(`\\b${escaped}\\b`).test(contentToSearch)) {
406
704
  keywordMatch = true;
407
705
  break;
408
706
  }
@@ -430,8 +728,10 @@ export async function selectAudits({
430
728
  changedFilesCount: changedFiles.length,
431
729
  // The ref the change set was actually diffed against. Epic-mode callers
432
730
  // assert this matches the requested Epic branch (Story #3362) so a
433
- // mis-pinned diff never reaches the audit-lens selector silently.
434
- resolvedRef: headRef,
731
+ // mis-pinned diff never reaches the audit-lens selector silently. `null`
732
+ // on the injected path: no ref was diffed, and naming one would invite
733
+ // exactly that assertion to pass against a diff nobody took.
734
+ resolvedRef: hasInjectedChangedFiles ? null : headRef,
435
735
  ticketTitle: ticket.title,
436
736
  },
437
737
  };
@@ -1,17 +1,17 @@
1
1
  /**
2
- * lib/audit-to-stories/seed-epic-from-findings.js
2
+ * lib/audit-to-stories/seed-from-findings.js
3
3
  *
4
- * Build the `--idea`-shaped seed markdown that `/plan` Phase 1
5
- * consumes when the operator picks the Single-Epic grouping mode.
4
+ * Build the `/plan --seed`-shaped one-pager markdown that the audit-to-
5
+ * stories Single-plan grouping path emits for `/plan` to consume.
6
6
  *
7
- * The seed renders the canonical one-pager sections so the idea-refinement
8
- * skill can sharpen it without having to invent context:
7
+ * The seed renders the canonical one-pager sections so the authoring
8
+ * pass can sharpen it without having to invent context:
9
9
  * - Problem Statement (aggregated severity profile)
10
10
  * - Recommended Direction (rollup of recommendations by dimension)
11
11
  * - Key Assumptions (carries the source-report links forward)
12
12
  * - MVP Scope (the proposed Stories, one bullet per group)
13
- * - Key Files (explicit file paths so /plan Phase 7 decompose
14
- * has concrete anchors)
13
+ * - Key Files (explicit file paths so `/plan` authoring has concrete
14
+ * anchors)
15
15
  * - Not Doing (out-of-scope items by convention)
16
16
  *
17
17
  * Pure: returns a string. The caller decides where to persist it.
@@ -112,14 +112,14 @@ function formatKeyAssumptions(sourceReports) {
112
112
  * @param {string[]} params.sourceReports — list of source report paths.
113
113
  * @returns {string}
114
114
  */
115
- export function buildEpicSeedMarkdown({ groups, findings, sourceReports }) {
115
+ export function buildPlanSeedMarkdown({ groups, findings, sourceReports }) {
116
116
  if (
117
117
  !Array.isArray(groups) ||
118
118
  !Array.isArray(findings) ||
119
119
  !Array.isArray(sourceReports)
120
120
  ) {
121
121
  throw new Error(
122
- 'buildEpicSeedMarkdown: groups, findings, sourceReports must all be arrays',
122
+ 'buildPlanSeedMarkdown: groups, findings, sourceReports must all be arrays',
123
123
  );
124
124
  }
125
125
  const problem = formatProblemStatement(findings);