mandrel 2.59.0 → 2.61.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 (678) hide show
  1. package/.agents/README.md +21 -19
  2. package/.agents/agents/acceptance-critic.md +24 -43
  3. package/.agents/agents/story-worker.md +20 -21
  4. package/.agents/docs/agentrc-reference.json +5 -84
  5. package/.agents/docs/configuration.md +48 -132
  6. package/.agents/docs/workflows.md +2 -2
  7. package/.agents/instructions.md +5 -8
  8. package/.agents/rules/ci-remediation.md +41 -8
  9. package/.agents/rules/gherkin-standards.md +4 -0
  10. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  11. package/.agents/schemas/agentrc.schema.json +16 -496
  12. package/.agents/schemas/story-deliver-terminal.schema.json +13 -3
  13. package/.agents/schemas/validation-evidence.schema.json +2 -1
  14. package/.agents/scripts/README.md +23 -13
  15. package/.agents/scripts/acceptance-eval.js +35 -169
  16. package/.agents/scripts/agents-bootstrap-github.js +27 -129
  17. package/.agents/scripts/apply-quality-bootstrap.js +4 -40
  18. package/.agents/scripts/audit-baselines.js +6 -27
  19. package/.agents/scripts/audit-labels-bootstrap.js +5 -29
  20. package/.agents/scripts/audit-to-stories.js +91 -361
  21. package/.agents/scripts/boot-sweep.js +19 -72
  22. package/.agents/scripts/bootstrap.js +74 -395
  23. package/.agents/scripts/ceremony-derive.js +10 -41
  24. package/.agents/scripts/check-arch-cycles.js +14 -64
  25. package/.agents/scripts/check-baselines.js +8 -48
  26. package/.agents/scripts/check-context-budget.js +105 -311
  27. package/.agents/scripts/check-cyclomatic.js +12 -44
  28. package/.agents/scripts/check-dead-exports.js +13 -64
  29. package/.agents/scripts/check-doc-links.js +38 -186
  30. package/.agents/scripts/check-gherkin-corpus.js +24 -127
  31. package/.agents/scripts/check-test-temp-hygiene.js +28 -169
  32. package/.agents/scripts/coverage-capture.js +34 -98
  33. package/.agents/scripts/deliver-light.js +25 -171
  34. package/.agents/scripts/deliver-recover.js +6 -42
  35. package/.agents/scripts/deliver-run.js +534 -0
  36. package/.agents/scripts/diagnose-friction.js +24 -116
  37. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  38. package/.agents/scripts/evidence-gate.js +23 -85
  39. package/.agents/scripts/file-ci-gap.js +57 -49
  40. package/.agents/scripts/generate-config-docs.js +30 -170
  41. package/.agents/scripts/generate-lens-checklists.js +8 -52
  42. package/.agents/scripts/generate-skills-index.js +14 -112
  43. package/.agents/scripts/generate-workflows-doc.js +10 -70
  44. package/.agents/scripts/git-cleanup.js +2 -34
  45. package/.agents/scripts/lib/Graph.js +24 -81
  46. package/.agents/scripts/lib/ITicketingProvider.js +47 -143
  47. package/.agents/scripts/lib/Logger.js +14 -76
  48. package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
  49. package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
  50. package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
  51. package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
  52. package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
  53. package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
  54. package/.agents/scripts/lib/audit-baselines/read.js +3 -16
  55. package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
  56. package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
  57. package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
  58. package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
  59. package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
  60. package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
  61. package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
  62. package/.agents/scripts/lib/audit-suite/findings.js +12 -52
  63. package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
  64. package/.agents/scripts/lib/audit-suite/index.js +1 -15
  65. package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
  66. package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
  67. package/.agents/scripts/lib/audit-suite/runner.js +13 -43
  68. package/.agents/scripts/lib/audit-suite/selector.js +49 -349
  69. package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
  70. package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
  71. package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
  72. package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
  73. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
  74. package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
  75. package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
  76. package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
  77. package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
  78. package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
  79. package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
  80. package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
  81. package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
  82. package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
  83. package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
  84. package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
  85. package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
  86. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
  87. package/.agents/scripts/lib/baseline-loader.js +12 -51
  88. package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
  89. package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
  90. package/.agents/scripts/lib/baselines/components.js +10 -61
  91. package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
  92. package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -19
  93. package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
  94. package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
  95. package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
  96. package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
  97. package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
  98. package/.agents/scripts/lib/baselines/envelope.js +13 -129
  99. package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
  100. package/.agents/scripts/lib/baselines/git-base.js +23 -142
  101. package/.agents/scripts/lib/baselines/kernel.js +11 -111
  102. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
  103. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
  104. package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
  105. package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
  106. package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
  107. package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
  108. package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
  109. package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
  110. package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
  111. package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
  112. package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
  113. package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
  114. package/.agents/scripts/lib/baselines/path-canon.js +19 -128
  115. package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
  116. package/.agents/scripts/lib/baselines/reader.js +14 -107
  117. package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
  118. package/.agents/scripts/lib/baselines/scope.js +11 -135
  119. package/.agents/scripts/lib/baselines/writer.js +16 -149
  120. package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
  121. package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
  122. package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
  123. package/.agents/scripts/lib/bdd-step-index.js +26 -100
  124. package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
  125. package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
  126. package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
  127. package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
  128. package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
  129. package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
  130. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
  131. package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
  132. package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
  133. package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
  134. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
  135. package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
  136. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
  137. package/.agents/scripts/lib/bootstrap/summary.js +1 -8
  138. package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
  139. package/.agents/scripts/lib/branch-name-guard.js +4 -23
  140. package/.agents/scripts/lib/changed-files.js +39 -121
  141. package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
  142. package/.agents/scripts/lib/checks/index.js +18 -101
  143. package/.agents/scripts/lib/checks/loop-health.js +11 -53
  144. package/.agents/scripts/lib/checks/state.js +16 -91
  145. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
  146. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
  147. package/.agents/scripts/lib/child-exec.js +39 -108
  148. package/.agents/scripts/lib/cli/standard-args.js +9 -116
  149. package/.agents/scripts/lib/cli-args.js +31 -146
  150. package/.agents/scripts/lib/cli-usage.js +5 -27
  151. package/.agents/scripts/lib/cli-utils.js +2 -12
  152. package/.agents/scripts/lib/close-validation/commands.js +13 -76
  153. package/.agents/scripts/lib/close-validation/gates.js +92 -331
  154. package/.agents/scripts/lib/close-validation/process.js +121 -151
  155. package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
  156. package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
  157. package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
  158. package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
  159. package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
  160. package/.agents/scripts/lib/close-validation/runner.js +53 -110
  161. package/.agents/scripts/lib/command-header.js +6 -28
  162. package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
  163. package/.agents/scripts/lib/config/baselines.js +3 -14
  164. package/.agents/scripts/lib/config/ci.js +8 -38
  165. package/.agents/scripts/lib/config/commands.js +1 -15
  166. package/.agents/scripts/lib/config/defaults.js +4 -33
  167. package/.agents/scripts/lib/config/delivery-routing.js +6 -34
  168. package/.agents/scripts/lib/config/explain.js +10 -83
  169. package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
  170. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +3 -31
  171. package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
  172. package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
  173. package/.agents/scripts/lib/config/gates/index.js +2 -17
  174. package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
  175. package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
  176. package/.agents/scripts/lib/config/gates/shared.js +4 -64
  177. package/.agents/scripts/lib/config/github.js +4 -22
  178. package/.agents/scripts/lib/config/limits.js +4 -57
  179. package/.agents/scripts/lib/config/paths.js +2 -21
  180. package/.agents/scripts/lib/config/qa.js +4 -38
  181. package/.agents/scripts/lib/config/quality.js +76 -432
  182. package/.agents/scripts/lib/config/runners.js +12 -56
  183. package/.agents/scripts/lib/config/runtime.js +13 -57
  184. package/.agents/scripts/lib/config/shared.js +2 -16
  185. package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
  186. package/.agents/scripts/lib/config/temp-paths.js +40 -280
  187. package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
  188. package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
  189. package/.agents/scripts/lib/config-resolver.js +11 -52
  190. package/.agents/scripts/lib/config-schema-shared.js +1 -4
  191. package/.agents/scripts/lib/config-settings-schema-delivery.js +16 -291
  192. package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
  193. package/.agents/scripts/lib/config-settings-schema.js +37 -274
  194. package/.agents/scripts/lib/coverage-baseline.js +20 -110
  195. package/.agents/scripts/lib/coverage-capture-fullscope.js +18 -35
  196. package/.agents/scripts/lib/coverage-capture-incremental.js +15 -45
  197. package/.agents/scripts/lib/coverage-capture-usage.js +8 -25
  198. package/.agents/scripts/lib/coverage-capture.js +99 -224
  199. package/.agents/scripts/lib/coverage-utils.js +14 -79
  200. package/.agents/scripts/lib/cpu-pool.js +17 -123
  201. package/.agents/scripts/lib/crap-baseline-join.js +16 -88
  202. package/.agents/scripts/lib/crap-coordinates.js +6 -25
  203. package/.agents/scripts/lib/crap-engine.js +40 -153
  204. package/.agents/scripts/lib/crap-method-identity.js +16 -78
  205. package/.agents/scripts/lib/crap-utils.js +31 -155
  206. package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
  207. package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
  208. package/.agents/scripts/lib/dead-exports-knip.js +18 -56
  209. package/.agents/scripts/lib/dead-exports-mode.js +5 -24
  210. package/.agents/scripts/lib/degraded-mode.js +3 -26
  211. package/.agents/scripts/lib/dependency-parser.js +8 -40
  212. package/.agents/scripts/lib/dependency-version.js +13 -35
  213. package/.agents/scripts/lib/detect-package-manager.js +6 -36
  214. package/.agents/scripts/lib/doc-tiers.js +22 -124
  215. package/.agents/scripts/lib/duplicate-search.js +8 -72
  216. package/.agents/scripts/lib/env-loader.js +5 -27
  217. package/.agents/scripts/lib/error-redactor.js +6 -31
  218. package/.agents/scripts/lib/errors/index.js +2 -22
  219. package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
  220. package/.agents/scripts/lib/escomplex-kernel.js +21 -123
  221. package/.agents/scripts/lib/feedback-loop/graduator-core.js +94 -419
  222. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
  223. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -149
  224. package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
  225. package/.agents/scripts/lib/findings/classify-finding.js +14 -69
  226. package/.agents/scripts/lib/findings/promote-finding.js +14 -112
  227. package/.agents/scripts/lib/findings/provenance-field.js +11 -52
  228. package/.agents/scripts/lib/findings/route-finding.js +37 -255
  229. package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
  230. package/.agents/scripts/lib/findings/severity.js +18 -104
  231. package/.agents/scripts/lib/format-generated-json.js +12 -44
  232. package/.agents/scripts/lib/full-suite-lock.js +160 -429
  233. package/.agents/scripts/lib/full-suite-queue.js +213 -0
  234. package/.agents/scripts/lib/gates/baseline-store.js +5 -9
  235. package/.agents/scripts/lib/gates/friction.js +1 -3
  236. package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
  237. package/.agents/scripts/lib/gh-exec.js +123 -191
  238. package/.agents/scripts/lib/git/cached-fetch.js +9 -52
  239. package/.agents/scripts/lib/git/sync-from-base.js +15 -107
  240. package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
  241. package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
  242. package/.agents/scripts/lib/git-utils.js +37 -161
  243. package/.agents/scripts/lib/github/framework-repo.js +8 -71
  244. package/.agents/scripts/lib/github-url.js +2 -17
  245. package/.agents/scripts/lib/import-graph.js +11 -38
  246. package/.agents/scripts/lib/install-cmd-parser.js +4 -13
  247. package/.agents/scripts/lib/json-utils.js +3 -18
  248. package/.agents/scripts/lib/label-constants.js +16 -111
  249. package/.agents/scripts/lib/label-taxonomy.js +4 -30
  250. package/.agents/scripts/lib/maintainability-engine.js +12 -80
  251. package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
  252. package/.agents/scripts/lib/maintainability-utils.js +16 -92
  253. package/.agents/scripts/lib/mandrel-catalog.js +12 -70
  254. package/.agents/scripts/lib/notifications/notifier.js +13 -38
  255. package/.agents/scripts/lib/npm-scripts.js +4 -23
  256. package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
  257. package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
  258. package/.agents/scripts/lib/observability/signal-validator.js +5 -37
  259. package/.agents/scripts/lib/observability/signals-writer.js +11 -121
  260. package/.agents/scripts/lib/observability/source-classifier.js +22 -203
  261. package/.agents/scripts/lib/observability/terse-result.js +14 -47
  262. package/.agents/scripts/lib/onboard/init-tail.js +13 -74
  263. package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
  264. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
  265. package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
  266. package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
  267. package/.agents/scripts/lib/orchestration/ceremony-routing.js +28 -156
  268. package/.agents/scripts/lib/orchestration/change-set.js +7 -36
  269. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
  270. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
  271. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
  272. package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
  273. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
  274. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
  275. package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
  276. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
  277. package/.agents/scripts/lib/orchestration/check-state.js +92 -0
  278. package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
  279. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +121 -157
  280. package/.agents/scripts/lib/orchestration/code-review.js +24 -128
  281. package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
  282. package/.agents/scripts/lib/orchestration/complexity-gate.js +118 -462
  283. package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
  284. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
  285. package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
  286. package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
  287. package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
  288. package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
  289. package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
  290. package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
  291. package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
  292. package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
  293. package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
  294. package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
  295. package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
  296. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
  297. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
  298. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
  299. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
  300. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
  301. package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
  302. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
  303. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
  304. package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
  305. package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
  306. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
  307. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
  308. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
  309. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
  310. package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
  311. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
  313. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
  314. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
  315. package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
  316. package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
  317. package/.agents/scripts/lib/orchestration/light-suitability.js +37 -307
  318. package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
  319. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
  320. package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
  321. package/.agents/scripts/lib/orchestration/plan-context.js +55 -318
  322. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
  323. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
  324. package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
  325. package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
  326. package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
  327. package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
  328. package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +16 -78
  329. package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
  330. package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
  331. package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
  332. package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
  333. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
  334. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
  335. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +71 -289
  336. package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
  337. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +96 -362
  338. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +9 -39
  339. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +60 -186
  340. package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
  341. package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
  342. package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
  343. package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
  344. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
  345. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
  346. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
  347. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
  348. package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
  349. package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
  350. package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
  351. package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
  352. package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
  353. package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
  354. package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
  355. package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
  356. package/.agents/scripts/lib/orchestration/review-depth.js +12 -91
  357. package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
  358. package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
  359. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
  360. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
  361. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
  362. package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
  363. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
  364. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
  365. package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
  366. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
  367. package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
  368. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
  369. package/.agents/scripts/lib/orchestration/run-epilogue.js +245 -326
  370. package/.agents/scripts/lib/orchestration/run-scoped-config.js +55 -159
  371. package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
  372. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
  373. package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
  374. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
  375. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +20 -82
  376. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
  377. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
  378. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
  379. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
  380. package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +96 -0
  381. package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
  382. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
  383. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
  384. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
  385. package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
  386. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
  387. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
  388. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
  389. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
  390. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
  391. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
  392. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
  393. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +180 -273
  394. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
  395. package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
  396. package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
  397. package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
  398. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
  399. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
  400. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
  401. package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
  402. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -200
  403. package/.agents/scripts/lib/orchestration/story-follow-ups.js +167 -252
  404. package/.agents/scripts/lib/orchestration/story-init-envelope.js +52 -0
  405. package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
  406. package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
  407. package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -135
  408. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
  409. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
  410. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
  411. package/.agents/scripts/lib/orchestration/ticket-validator.js +63 -344
  412. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
  413. package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -261
  414. package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
  415. package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
  416. package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
  417. package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
  418. package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
  419. package/.agents/scripts/lib/path-security.js +3 -6
  420. package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
  421. package/.agents/scripts/lib/preflight-runner.js +13 -69
  422. package/.agents/scripts/lib/process-group.js +143 -0
  423. package/.agents/scripts/lib/project-root.js +2 -8
  424. package/.agents/scripts/lib/provider-factory.js +2 -25
  425. package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
  426. package/.agents/scripts/lib/qa/qa-session.js +15 -69
  427. package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
  428. package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
  429. package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
  430. package/.agents/scripts/lib/reserved-test-ids.js +9 -47
  431. package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
  432. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
  433. package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
  434. package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
  435. package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
  436. package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
  437. package/.agents/scripts/lib/signals/detectors/common.js +12 -38
  438. package/.agents/scripts/lib/signals/index.js +2 -19
  439. package/.agents/scripts/lib/signals/schema.js +14 -109
  440. package/.agents/scripts/lib/signals/write.js +2 -11
  441. package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
  442. package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
  443. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
  444. package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
  445. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
  446. package/.agents/scripts/lib/single-story-sweep.js +14 -97
  447. package/.agents/scripts/lib/skills/parse-skill.js +13 -59
  448. package/.agents/scripts/lib/skills/skills-index.js +8 -29
  449. package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
  450. package/.agents/scripts/lib/source-extensions.js +11 -42
  451. package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
  452. package/.agents/scripts/lib/stdio-flush.js +9 -36
  453. package/.agents/scripts/lib/story-adjacency.js +8 -40
  454. package/.agents/scripts/lib/story-body/body-format-lints.js +51 -66
  455. package/.agents/scripts/lib/story-body/footer-block.js +11 -44
  456. package/.agents/scripts/lib/story-body/story-body.js +123 -344
  457. package/.agents/scripts/lib/temp-retention.js +42 -143
  458. package/.agents/scripts/lib/templates/decomposer-prompts.js +18 -80
  459. package/.agents/scripts/lib/test-env.js +12 -65
  460. package/.agents/scripts/lib/test-run-credit.js +10 -65
  461. package/.agents/scripts/lib/test-runner-contract.js +19 -74
  462. package/.agents/scripts/lib/test-temp.js +38 -184
  463. package/.agents/scripts/lib/test-tiers.js +12 -96
  464. package/.agents/scripts/lib/ticket-body-sections.js +21 -96
  465. package/.agents/scripts/lib/transpile.js +15 -74
  466. package/.agents/scripts/lib/util/concurrent-map.js +6 -25
  467. package/.agents/scripts/lib/util/parse-id-list.js +8 -34
  468. package/.agents/scripts/lib/util/poll-loop.js +8 -28
  469. package/.agents/scripts/lib/util/with-timeout.js +2 -11
  470. package/.agents/scripts/lib/validation-evidence.js +21 -96
  471. package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
  472. package/.agents/scripts/lib/wave-runner/live-probe.js +67 -209
  473. package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
  474. package/.agents/scripts/lib/workers/crap-worker.js +11 -64
  475. package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
  476. package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
  477. package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
  478. package/.agents/scripts/lib/workflow-closure.js +22 -105
  479. package/.agents/scripts/lib/workspace-provisioner.js +16 -54
  480. package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
  481. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
  482. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
  483. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
  484. package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
  485. package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
  486. package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
  487. package/.agents/scripts/lib/worktree-manager.js +15 -40
  488. package/.agents/scripts/lint-issue-body.js +12 -68
  489. package/.agents/scripts/mandrel-update-preflight.js +10 -70
  490. package/.agents/scripts/merge-baseline.js +30 -105
  491. package/.agents/scripts/nav-registry-diff.js +22 -108
  492. package/.agents/scripts/notify.js +12 -69
  493. package/.agents/scripts/plan-context.js +97 -92
  494. package/.agents/scripts/plan-critics.js +12 -66
  495. package/.agents/scripts/plan-persist.js +71 -137
  496. package/.agents/scripts/plan-run-epilogue.js +20 -43
  497. package/.agents/scripts/pr-watch-with-update.js +79 -263
  498. package/.agents/scripts/providers/github/auth.js +3 -8
  499. package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
  500. package/.agents/scripts/providers/github/board-add.js +5 -21
  501. package/.agents/scripts/providers/github/branch-protection.js +11 -43
  502. package/.agents/scripts/providers/github/cache.js +2 -14
  503. package/.agents/scripts/providers/github/comments.js +7 -40
  504. package/.agents/scripts/providers/github/compose.js +3 -19
  505. package/.agents/scripts/providers/github/errors.js +22 -125
  506. package/.agents/scripts/providers/github/issues.js +31 -123
  507. package/.agents/scripts/providers/github/labels.js +24 -124
  508. package/.agents/scripts/providers/github/mappers.js +5 -27
  509. package/.agents/scripts/providers/github/merge-methods.js +3 -22
  510. package/.agents/scripts/providers/github/project-board.js +2 -17
  511. package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
  512. package/.agents/scripts/providers/github/request-helpers.js +5 -32
  513. package/.agents/scripts/providers/github/search-budget.js +9 -39
  514. package/.agents/scripts/providers/github/search-query.js +5 -26
  515. package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
  516. package/.agents/scripts/providers/github/sub-issues.js +7 -36
  517. package/.agents/scripts/providers/github/tickets.js +32 -134
  518. package/.agents/scripts/providers/github.js +18 -59
  519. package/.agents/scripts/prune-plan-run-labels.js +12 -46
  520. package/.agents/scripts/quality-preview.js +35 -220
  521. package/.agents/scripts/resolve-doc-tiers.js +3 -26
  522. package/.agents/scripts/resolve-stories.js +16 -67
  523. package/.agents/scripts/resync-status-column.js +6 -25
  524. package/.agents/scripts/run-tests.js +29 -104
  525. package/.agents/scripts/single-story-close.js +23 -135
  526. package/.agents/scripts/single-story-confirm-merge.js +32 -139
  527. package/.agents/scripts/single-story-init.js +47 -259
  528. package/.agents/scripts/stories-wave-tick.js +179 -415
  529. package/.agents/scripts/sync-agentrc.js +3 -21
  530. package/.agents/scripts/sync-claude-agents.js +9 -55
  531. package/.agents/scripts/sync-claude-commands.js +20 -110
  532. package/.agents/scripts/test-wrapper.js +6 -43
  533. package/.agents/scripts/update-coverage-baseline.js +5 -22
  534. package/.agents/scripts/update-crap-baseline.js +7 -30
  535. package/.agents/scripts/update-duplication-baseline.js +16 -92
  536. package/.agents/scripts/update-maintainability-baseline.js +8 -62
  537. package/.agents/scripts/update-ticket-state.js +1 -7
  538. package/.agents/scripts/validate-skills.js +6 -26
  539. package/.agents/skills/core/gates-and-baselines/reference.md +0 -1
  540. package/.agents/skills/skills.index.json +2 -2
  541. package/.agents/skills/stack/qa/playwright/SKILL.md +26 -0
  542. package/.agents/templates/agent-protocol.md +2 -2
  543. package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
  544. package/.agents/workflows/audit-accessibility.md +4 -7
  545. package/.agents/workflows/audit-adrs.md +3 -6
  546. package/.agents/workflows/audit-architecture.md +3 -11
  547. package/.agents/workflows/audit-baselines.md +6 -9
  548. package/.agents/workflows/audit-clean-code.md +8 -12
  549. package/.agents/workflows/audit-data-model.md +3 -7
  550. package/.agents/workflows/audit-dependencies.md +4 -7
  551. package/.agents/workflows/audit-devops.md +4 -8
  552. package/.agents/workflows/audit-documentation.md +1 -4
  553. package/.agents/workflows/audit-mobile.md +4 -7
  554. package/.agents/workflows/audit-navigability.md +3 -6
  555. package/.agents/workflows/audit-performance.md +2 -4
  556. package/.agents/workflows/audit-privacy.md +4 -7
  557. package/.agents/workflows/audit-quality.md +4 -7
  558. package/.agents/workflows/audit-security.md +4 -7
  559. package/.agents/workflows/audit-seo.md +4 -7
  560. package/.agents/workflows/audit-sre.md +4 -7
  561. package/.agents/workflows/audit-to-stories.md +17 -30
  562. package/.agents/workflows/audit-ux-ui.md +4 -7
  563. package/.agents/workflows/helpers/acceptance-self-eval.md +84 -157
  564. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  565. package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
  566. package/.agents/workflows/helpers/code-review.md +4 -2
  567. package/.agents/workflows/helpers/deliver-digest.md +37 -28
  568. package/.agents/workflows/helpers/deliver-light.md +92 -101
  569. package/.agents/workflows/helpers/deliver-reference.md +162 -220
  570. package/.agents/workflows/helpers/deliver-story-reference.md +197 -607
  571. package/.agents/workflows/helpers/deliver-story.md +17 -18
  572. package/.agents/workflows/helpers/plan-reference.md +125 -167
  573. package/.agents/workflows/helpers/qa-core.md +12 -0
  574. package/.agents/workflows/mandrel-deliver.md +47 -31
  575. package/.agents/workflows/mandrel-plan.md +22 -21
  576. package/.agents/workflows/mandrel-update.md +36 -21
  577. package/.agents/workflows/memory-consolidate.md +1 -1
  578. package/.agents/workflows/qa-assist.md +27 -71
  579. package/.agents/workflows/qa-explore.md +19 -59
  580. package/.agents/workflows/qa-run.md +11 -33
  581. package/README.md +1 -1
  582. package/bin/mandrel.js +5 -46
  583. package/bin/postinstall.js +18 -107
  584. package/docs/CHANGELOG.md +60 -0
  585. package/lib/cli/doctor.js +11 -71
  586. package/lib/cli/init.js +26 -165
  587. package/lib/cli/migrate.js +5 -64
  588. package/lib/cli/registry.js +84 -467
  589. package/lib/cli/sync-agents.js +4 -64
  590. package/lib/cli/sync-commands.js +11 -64
  591. package/lib/cli/sync.js +34 -213
  592. package/lib/cli/uninstall.js +40 -219
  593. package/lib/cli/update.js +326 -523
  594. package/lib/cli/version-check.js +8 -72
  595. package/lib/cli/version-helpers.js +14 -87
  596. package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
  597. package/lib/migrations/index.js +17 -92
  598. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
  599. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
  600. package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
  601. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
  602. package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
  603. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
  604. package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
  605. package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
  606. package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +21 -0
  607. package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
  608. package/package.json +17 -14
  609. package/.agents/docs/SDLC.md +0 -590
  610. package/.agents/docs/quality-gates.md +0 -1179
  611. package/.agents/rules/known-tooling-behavior.md +0 -150
  612. package/.agents/rules/orchestration-error-handling.md +0 -61
  613. package/.agents/rules/test-seams.md +0 -59
  614. package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
  615. package/.agents/schemas/baselines/lint.schema.json +0 -47
  616. package/.agents/schemas/model-attribution.schema.json +0 -53
  617. package/.agents/scripts/check-action-pinning.js +0 -260
  618. package/.agents/scripts/check-audit-attribution.js +0 -302
  619. package/.agents/scripts/check-baseline-drift.js +0 -211
  620. package/.agents/scripts/check-baseline-scope.js +0 -362
  621. package/.agents/scripts/check-generated-validator.js +0 -202
  622. package/.agents/scripts/check-knip-entries.js +0 -159
  623. package/.agents/scripts/check-lifecycle-lint.js +0 -294
  624. package/.agents/scripts/check-pinned-override-notes.js +0 -102
  625. package/.agents/scripts/check-schema-references.js +0 -366
  626. package/.agents/scripts/check-test-portability.js +0 -512
  627. package/.agents/scripts/check-workflow-citations.js +0 -332
  628. package/.agents/scripts/check-workflow-cli-lint.js +0 -299
  629. package/.agents/scripts/check-workflow-timeouts.js +0 -291
  630. package/.agents/scripts/install-matrix-assert.js +0 -326
  631. package/.agents/scripts/lib/audit-advisories.js +0 -195
  632. package/.agents/scripts/lib/audit-attribution.js +0 -134
  633. package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
  634. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
  635. package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
  636. package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
  637. package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
  638. package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
  639. package/.agents/scripts/lib/c8-cli-path.js +0 -21
  640. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
  641. package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
  642. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
  643. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
  644. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
  645. package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
  646. package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
  647. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
  648. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
  649. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
  650. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
  651. package/.agents/scripts/lib/fs-walk.js +0 -52
  652. package/.agents/scripts/lib/knip-config-resolver.js +0 -181
  653. package/.agents/scripts/lib/knip-entry-sync.js +0 -452
  654. package/.agents/scripts/lib/orchestration/model-attribution.js +0 -418
  655. package/.agents/scripts/lib/orchestration/story-plan-state.js +0 -33
  656. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +0 -67
  657. package/.agents/scripts/lib/pinned-override-notes.js +0 -88
  658. package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
  659. package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
  660. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
  661. package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
  662. package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
  663. package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
  664. package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
  665. package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
  666. package/.agents/scripts/lib/test-isolate/runner.js +0 -483
  667. package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
  668. package/.agents/scripts/lib/test-profile/render-report.js +0 -45
  669. package/.agents/scripts/lint-label-vocabulary.js +0 -214
  670. package/.agents/scripts/post-structured-comment.js +0 -127
  671. package/.agents/scripts/provision-git-hooks.js +0 -85
  672. package/.agents/scripts/prune-baseline-orphans.js +0 -181
  673. package/.agents/scripts/run-coverage.js +0 -197
  674. package/.agents/scripts/run-lint.js +0 -133
  675. package/.agents/scripts/run-test-profile.js +0 -129
  676. package/.agents/scripts/run-verify.js +0 -118
  677. package/.agents/scripts/test-isolate.js +0 -55
  678. package/.agents/scripts/update-dead-exports-baseline.js +0 -321
@@ -1,53 +1,21 @@
1
1
  // .agents/scripts/lib/story-body/story-body.js
2
2
  /**
3
- * Canonical Story-body parser/serializer (Gap 1, Epic #3211).
4
- *
5
- * This module is the single source of truth for the Story body shape.
6
- * Every consumer that reads or writes a structured Story body MUST go
7
- * through these exports — do not inline ad-hoc parsing elsewhere.
8
- *
9
- * ## Structured Story body shape
10
- *
11
- * ```js
12
- * {
13
- * goal: string, // one-sentence purpose
14
- * slicing: string, // v2 intra-Story delivery slice plan (optional; '' when absent)
15
- * spec: string, // folded Tech Spec text block (optional; '' when absent)
16
- * changes: PathEntry[], // files/globs this Story touches
17
- * acceptance: string[], // observable criteria
18
- * verify: string[], // exact commands / tier annotation
19
- * references: PathEntry[], // read-only paths (optional)
20
- * non_goals: string[], // negative-scope bullets (optional, advisory)
21
- * depends_on: string[], // blocker story slugs or #ids
22
- * }
23
- * ```
24
- *
25
- * Where `PathEntry` is:
26
- * - `{ path: string, assumption: "creates"|"refactors-existing"|"exists"|"deletes" }`
27
- * (canonical form — string bullets are rejected at parse time)
28
- *
29
- * ## Round-trip contract
30
- *
31
- * `serialize(parse(markdown)) === markdown` when the input is already
32
- * in the canonical serialized form. Non-canonical whitespace or
33
- * section ordering may produce a normalized (but equivalent) output.
34
- *
35
- * The parser MUST fail closed: a body that cannot be mapped to the
36
- * canonical shape throws `StoryBodyParseError` — it does NOT silently
37
- * coerce malformed input. This prevents a corrupt body from supplying
38
- * wrong `depends_on` edges that reorder the wave DAG.
3
+ * Canonical Story-body parser/serializer — the single source of truth for
4
+ * the Story body shape. The parser fails closed: a body that cannot be mapped
5
+ * to the canonical shape throws, so a corrupt body cannot supply wrong
6
+ * `depends_on` edges. `serialize(parse(md)) === md` for canonical input.
39
7
  *
40
8
  * @module story-body
41
9
  */
42
10
 
43
11
  import { FILE_ASSUMPTION_VALUES } from '../orchestration/file-assumption-enum.js';
44
- import { suggestPathEntryFix } from './body-format-lints.js';
12
+ import {
13
+ isProseBullet,
14
+ matchBarePathToken,
15
+ suggestPathEntryFix,
16
+ } from './body-format-lints.js';
45
17
  import { isFooterSeparator, parseFooterBlockedByRefs } from './footer-block.js';
46
18
 
47
- // ---------------------------------------------------------------------------
48
- // Public types (JSDoc only — no runtime schema file)
49
- // ---------------------------------------------------------------------------
50
-
51
19
  /**
52
20
  * @typedef {'creates'|'refactors-existing'|'exists'|'deletes'} AssumptionEnum
53
21
  */
@@ -62,52 +30,45 @@ import { isFooterSeparator, parseFooterBlockedByRefs } from './footer-block.js';
62
30
 
63
31
  /**
64
32
  * @typedef {object} StoryBody
65
- * @property {string} goal - One-sentence purpose statement.
66
- * @property {string} slicing - Optional v2 intra-Story delivery slice plan text block; '' when absent.
67
- * @property {string} spec - Optional folded Tech Spec text block; '' when absent.
68
- * @property {PathEntry[]} changes - Files / globs this Story modifies.
69
- * @property {string[]} acceptance - Observable acceptance criteria.
70
- * @property {string[]} verify - Exact commands the deliverer runs.
71
- * @property {PathEntry[]} references - Read-only paths (may be empty).
72
- * @property {string[]} non_goals - Negative-scope bullets (advisory; may be empty).
33
+ * @property {string} goal
34
+ * @property {string} slicing - Intra-Story slice plan; '' when absent.
35
+ * @property {string} spec - Folded Tech Spec; '' when absent.
36
+ * @property {PathEntry[]} changes
37
+ * @property {string[]} acceptance
38
+ * @property {string[]} verify
39
+ * @property {PathEntry[]} references - Read-only paths.
40
+ * @property {string[]} non_goals - Advisory negative scope.
73
41
  * @property {string[]} depends_on - Blocking story slugs / issue refs.
74
42
  */
75
43
 
76
44
  /**
77
45
  * @typedef {object} ParseResult
78
- * @property {StoryBody} body - The parsed structured body.
79
- * @property {string[]} warnings - Non-fatal issues (e.g. unstructured-body).
80
- * @property {ParseInfo} info - Metadata about the parse.
46
+ * @property {StoryBody} body
47
+ * @property {string[]} warnings
48
+ * @property {ParseInfo} info
81
49
  */
82
50
 
83
51
  /**
84
52
  * @typedef {object} ParseInfo
85
- * @property {boolean} hasGoalSection - Whether a `## Goal` section was found.
86
- * @property {boolean} hasChangesSection - Whether a `## Changes` section was found.
87
- * @property {boolean} hasAcceptanceSection - Whether a `## Acceptance` section was found.
88
- * @property {boolean} hasVerifySection - Whether a `## Verify` section was found.
89
- * @property {boolean} hasReferencesSection - Whether a `## References` section was found.
90
- * @property {boolean} hasNonGoalsSection - Whether a `## Non-Goals` section was found.
91
- * @property {boolean} hasSlicingSection - Whether a `## Slicing` section was found (v2 folded slice plan).
92
- * @property {boolean} hasSpecSection - Whether a `## Spec` section was found (folded Tech Spec).
53
+ * @property {boolean} hasGoalSection
54
+ * @property {boolean} hasChangesSection
55
+ * @property {boolean} hasAcceptanceSection
56
+ * @property {boolean} hasVerifySection
57
+ * @property {boolean} hasReferencesSection
58
+ * @property {boolean} hasNonGoalsSection
59
+ * @property {boolean} hasSlicingSection
60
+ * @property {boolean} hasSpecSection
93
61
  * @property {boolean} isUnstructuredBody - True when no structured sections were found.
94
62
  */
95
63
 
96
64
  /**
97
65
  * @typedef {object} SerializeOptions
98
66
  * @property {boolean} [includeFooter=false] - Include `---\nparent/blocked-by` footer.
99
- * @property {object} [footer] - Footer fields when `includeFooter` is true.
100
- * @property {number} [footer.parent] - Parent feature issue number.
67
+ * @property {object} [footer]
68
+ * @property {number} [footer.parent]
101
69
  */
102
70
 
103
- // ---------------------------------------------------------------------------
104
- // Error class
105
- // ---------------------------------------------------------------------------
106
-
107
- /**
108
- * Thrown when the Story body cannot be parsed into the canonical shape.
109
- * The parser fails closed — do not catch this to silently continue.
110
- */
71
+ /** Thrown when a Story body cannot be parsed; never catch to continue. */
111
72
  export class StoryBodyParseError extends Error {
112
73
  /**
113
74
  * @param {string} message
@@ -121,13 +82,7 @@ export class StoryBodyParseError extends Error {
121
82
  }
122
83
  }
123
84
 
124
- // ---------------------------------------------------------------------------
125
- // Section heading map
126
- // ---------------------------------------------------------------------------
127
-
128
- // Heading text → body field name. Keys are normalized: lower-cased with `-`
129
- // folded to `_` (see splitSections), so the hyphenated `## Non-Goals` heading
130
- // maps to the `non_goals` field.
85
+ // Keys are lower-cased with `-` folded to `_` (see splitSections).
131
86
  const HEADING_TO_FIELD = new Map([
132
87
  ['goal', 'goal'],
133
88
  ['slicing', 'slicing'],
@@ -140,14 +95,7 @@ const HEADING_TO_FIELD = new Map([
140
95
  ]);
141
96
  const TEXT_BLOCK_FIELDS = new Set(['slicing', 'spec']);
142
97
 
143
- // ---------------------------------------------------------------------------
144
- // Helpers
145
- // ---------------------------------------------------------------------------
146
-
147
98
  /**
148
- * Strip leading `- ` or `- [ ] ` from a markdown list item, returning the
149
- * raw content.
150
- *
151
99
  * @param {string} line
152
100
  * @returns {string}
153
101
  */
@@ -155,88 +103,87 @@ function stripListMarker(line) {
155
103
  return line.replace(/^-\s+(?:\[\s*[xX ]?\s*\]\s+)?/, '').trim();
156
104
  }
157
105
 
158
- // Humanized PathEntry bullet (Story #4600): `path` — assumption. This is the
159
- // shape serialize() now emits for `## Changes` / `## References`; the legacy
160
- // inline-JSON object bullet remains accepted at parse time indefinitely (live
161
- // issue bodies are never rewritten).
106
+ // `path` — assumption: the shape serialize() emits. The inline-JSON bullet is
107
+ // still accepted at parse time because live issue bodies are never rewritten.
162
108
  const HUMANIZED_PATH_ENTRY_RE = /^`([^`]+)`\s+—\s+(\S+)$/;
163
109
 
164
- // AC-<n> presentation prefix on acceptance checkboxes (Story #4600). The
165
- // numbering is a stable 1-based human handle only — parse() strips it so the
166
- // top-level acceptance[] machine contract round-trips byte-identical.
167
- //
168
- // The lettered form (`AC-14a:`) is accepted too (Story #5323). Nothing emits
169
- // one — `serialize()` numbers from the array index — but a Story planned from
170
- // an existing ticket can copy one out of the source issue's rendered
171
- // checkboxes, and a body that already carries one must still parse to the
172
- // handle-free text or the round-trip invariant breaks for it alone. Trailing
173
- // whitespace is optional so `AC-3:text` normalises as readily as `AC-3: text`.
110
+ // Presentation-only `AC-<n>:` handle (lettered `AC-14a:` too, copied from
111
+ // source tickets); parse() strips it so acceptance[] round-trips.
174
112
  const AC_PREFIX_RE = /^AC-\d+[a-z]?:\s*/i;
175
113
 
176
- // Machine-managed marker lines a body authored before Story #5312 may still
177
- // carry: the `> **Wide:** <reason>` rationale line (Story #4600), the
178
- // `> 🏷️ Authored with Mandrel …` provenance line, and the trailing
179
- // `<!-- meta: {...} -->` block. Nothing writes them any more — the `wide` /
180
- // `reason_to_exist` fields and the provenance stamp went with the plan-time
181
- // sizing model — but live issue bodies are never rewritten, so the parser
182
- // still skips them wherever they appear rather than absorbing a stray line
183
- // into the last structured section. A skipped block is dropped on
184
- // re-serialize, which is the cutover working as intended.
114
+ // Retired machine-managed marker lines nothing writes any more. Live bodies
115
+ // still carry them, so the parser skips them rather than absorbing them into
116
+ // the last section; they are dropped on re-serialize.
185
117
  const WIDE_MARKER_LINE_RE = /^>\s*\*\*Wide:\*\*/;
186
118
  const AUTHORED_MARKER_LINE_RE = /^\s*>\s*🏷️\s+Authored with Mandrel\b/;
187
119
  const META_BLOCK_RE = /<!--\s*meta:[\s\S]*?-->/;
188
120
 
189
121
  /**
190
- * Parse a single `changes` / `references` bullet into a `PathEntry`.
191
- *
192
- * Accepted markdown shapes (both parsed indefinitely — live issue bodies
193
- * are never rewritten):
194
- * - Humanized bullet (canonical serialize() output since Story #4600):
195
- * `` `src/x.js` — refactors-existing ``
196
- * - Legacy inline-JSON object bullet:
197
- * `- { "path": "...", "assumption": "..." }`
198
- *
199
- * A structured object entry (from a parsed JSON body that was never
200
- * serialized to markdown) arrives as-is and is validated directly.
122
+ * Parse one `changes` / `references` bullet: bare path (`assumption: null`),
123
+ * humanized `` `path` — assumption ``, or inline-JSON object.
201
124
  *
202
125
  * @param {string|object} raw
203
126
  * @param {string[]} warnings
204
127
  * @returns {PathEntry}
205
128
  */
206
129
  function parsePathEntry(raw, warnings) {
207
- // Already a structured object (from a parsed JSON body, not markdown).
208
130
  if (raw !== null && typeof raw === 'object') {
209
131
  return pathEntryFromObject(raw);
210
132
  }
211
133
 
212
- const str = typeof raw === 'string' ? raw.trim() : String(raw).trim();
134
+ const str = String(raw).trim();
213
135
  if (str.length === 0) return null;
214
136
 
215
137
  const entry = pathEntryFromHumanized(str) ?? pathEntryFromInlineJson(str);
216
138
  if (entry) return entry;
139
+ return pathEntryFromBare(str);
140
+ }
217
141
 
142
+ /**
143
+ * Last shape tried, so it owns the rejection. A `{`-leading string here is
144
+ * malformed JSON, not a path. Prose and non-path tokens get distinct refusals
145
+ * because they need different fixes.
146
+ *
147
+ * @param {string} str
148
+ * @returns {PathEntry}
149
+ */
150
+ function pathEntryFromBare(str) {
151
+ const bare = str.startsWith('{') ? null : matchBarePathToken(str);
152
+ if (bare !== null) return { path: bare, assumption: null };
153
+
154
+ const shape = isProseBullet(str)
155
+ ? 'is prose, not a path'
156
+ : 'names no usable path';
218
157
  throw new StoryBodyParseError(
219
- `changes/references entry must be a { path, assumption } object; plain string bullets are no longer accepted: ${str.slice(0, 120)}${pathEntryFixIt(str)}`,
158
+ `changes/references entry ${shape} — a bullet must be a single ` +
159
+ `whitespace-free path token, or a { path, assumption } object: ` +
160
+ `${str.slice(0, 120)}${pathEntryFixIt(str)}`,
220
161
  { field: 'changes', raw: str },
221
162
  );
222
163
  }
223
164
 
224
165
  /**
225
- * Validate an already-structured `{ path, assumption }` object. Fails closed
226
- * on a malformed object.
166
+ * A canonical value (pinned), `null` (omitted — persist derives it), or
167
+ * `undefined` (not an assumption — a typo must fail closed).
227
168
  *
169
+ * @param {unknown} raw
170
+ * @returns {string|null|undefined}
171
+ */
172
+ function readAssumption(raw) {
173
+ if (FILE_ASSUMPTION_VALUES.includes(raw)) return raw;
174
+ return raw == null ? null : undefined;
175
+ }
176
+
177
+ /**
228
178
  * @param {object} raw
229
179
  * @returns {PathEntry}
230
180
  */
231
181
  function pathEntryFromObject(raw) {
232
- if (
233
- typeof raw.path === 'string' &&
234
- raw.path.trim().length > 0 &&
235
- FILE_ASSUMPTION_VALUES.includes(raw.assumption)
236
- ) {
237
- return { path: raw.path.trim(), assumption: raw.assumption };
182
+ const path = typeof raw.path === 'string' ? raw.path.trim() : '';
183
+ const assumption = readAssumption(raw.assumption);
184
+ if (path !== '' && assumption !== undefined) {
185
+ return { path, assumption };
238
186
  }
239
- // Malformed object: fail closed.
240
187
  throw new StoryBodyParseError(
241
188
  `changes/references entry is an object but not a valid PathEntry: ${JSON.stringify(raw)}`,
242
189
  { field: 'changes', raw: JSON.stringify(raw) },
@@ -244,10 +191,7 @@ function pathEntryFromObject(raw) {
244
191
  }
245
192
 
246
193
  /**
247
- * Parse the humanized bullet shape (the canonical serialize() output since
248
- * Story #4600): `` `path` — assumption ``. Returns `null` when the line is
249
- * not that shape at all; fails closed when the shape is recognized but the
250
- * fields are invalid.
194
+ * `null` when not the humanized shape; throws when recognized but invalid.
251
195
  *
252
196
  * @param {string} str
253
197
  * @returns {PathEntry|null}
@@ -259,7 +203,6 @@ function pathEntryFromHumanized(str) {
259
203
  if (path.length > 0 && FILE_ASSUMPTION_VALUES.includes(humanized[2])) {
260
204
  return { path, assumption: humanized[2] };
261
205
  }
262
- // Recognized the humanized shape but the fields are invalid: fail closed.
263
206
  throw new StoryBodyParseError(
264
207
  `changes/references entry is a humanized bullet but not a valid PathEntry: ${str.slice(0, 120)}${pathEntryFixIt(str)}`,
265
208
  { field: 'changes', raw: str },
@@ -267,11 +210,7 @@ function pathEntryFromHumanized(str) {
267
210
  }
268
211
 
269
212
  /**
270
- * Parse the legacy inline-JSON object bullet:
271
- * `{ "path": "...", "assumption": "..." }`. Returns `null` when the line is
272
- * not a JSON object at all (including a JSON parse failure — the caller then
273
- * rejects the plain-string form); fails closed when it parses to an object
274
- * without valid PathEntry fields.
213
+ * `null` when not a JSON object (the caller then tries the bare form).
275
214
  *
276
215
  * @param {string} str
277
216
  * @returns {PathEntry|null}
@@ -282,28 +221,16 @@ function pathEntryFromInlineJson(str) {
282
221
  try {
283
222
  parsed = JSON.parse(str);
284
223
  } catch {
285
- // JSON parse failed — the caller rejects the plain-string form.
286
224
  return null;
287
225
  }
288
- if (typeof parsed !== 'object' || parsed === null) return null;
289
- if (
290
- typeof parsed.path === 'string' &&
291
- FILE_ASSUMPTION_VALUES.includes(parsed.assumption)
292
- ) {
293
- return { path: parsed.path.trim(), assumption: parsed.assumption };
294
- }
295
- // Parsed successfully as JSON object but has invalid fields — fail closed.
296
- throw new StoryBodyParseError(
297
- `changes/references entry is a JSON object but not a valid PathEntry: ${str}`,
298
- { field: 'changes', raw: str },
299
- );
226
+ return parsed !== null && typeof parsed === 'object'
227
+ ? pathEntryFromObject(parsed)
228
+ : null;
300
229
  }
301
230
 
302
231
  /**
303
- * Build the ` Suggested fix: …` suffix for a rejected changes/references
304
- * bullet, when a `{ path, assumption }` object can be salvaged from it. Returns
305
- * an empty string when nothing is inferable, so callers can append it
306
- * unconditionally (Story #4684 — mechanical auto-fix in the failure output).
232
+ * ` Suggested fix: …` suffix for a rejected bullet, or '' when nothing is
233
+ * inferable.
307
234
  *
308
235
  * @param {string} raw The rejected bullet text.
309
236
  * @returns {string}
@@ -315,11 +242,7 @@ function pathEntryFixIt(raw) {
315
242
  }
316
243
 
317
244
  /**
318
- * Extract the `blocked by #N` lines from the footer block (text after
319
- * the last `---` separator). Returns an array of "#N" strings.
320
- *
321
- * Delegates to `./footer-block.js`, which owns the footer-block grammar
322
- * (Story #5046) so the body parser and the dispatch-edge parser cannot
245
+ * Delegates to footer-block.js so the body and dispatch-edge parsers cannot
323
246
  * disagree about what declares an edge.
324
247
  *
325
248
  * @param {string} footerBlock
@@ -330,15 +253,8 @@ function extractBlockedBy(footerBlock) {
330
253
  }
331
254
 
332
255
  /**
333
- * Split markdown into named sections plus a footer block.
334
- *
335
- * Returns `{ sections: Map<string, string[]>, footer: string }`.
336
- * Each map value is the raw non-empty content lines under that heading
337
- * (heading line stripped).
338
- *
339
- * A `---` followed by recognised footer keys (`parent:`, `Epic:`,
340
- * `blocked by`) marks the start of the footer block. Content after the
341
- * footer separator is NOT parsed as sections.
256
+ * Split markdown into named sections plus the footer block; content after
257
+ * the footer separator is not parsed as sections.
342
258
  *
343
259
  * @param {string} markdown
344
260
  * @returns {{ sections: Map<string, string[]>, footer: string, preamble: string }}
@@ -359,20 +275,9 @@ function splitSections(markdown) {
359
275
  break;
360
276
  }
361
277
 
362
- // Detect `## Heading` (canonical) or `### Heading` lines. GitHub Issue
363
- // Forms (Story #4227) render every field label as a level-3 heading
364
- // (`### Goal`), not the level-2 the canonical serializer emits, so the
365
- // parser accepts both levels. Any other heading depth is ignored.
366
- //
367
- // The token class is `[\w-]+` (not bare `\w+`) so a single hyphenated
368
- // heading word — the canonical `## Non-Goals` negative-scope section —
369
- // matches as one token. The captured name is normalized (lower-cased,
370
- // `-` folded to `_`) before the HEADING_TO_FIELD lookup, so `Non-Goals`
371
- // resolves to the `non_goals` field. Multi-word headings that contain a
372
- // space (`## Out of Scope`, `## Agent Prompts`) still do NOT match this
373
- // single-token shape — they fall through to the section-terminator branch
374
- // below, which closes the open section. The chosen canonical spelling is
375
- // therefore the hyphenated single token `## Non-Goals`.
278
+ // `##` or `###` (GitHub Issue Forms render labels as level 3). The token
279
+ // is a single `[\w-]+` word so `Non-Goals` matches; multi-word headings
280
+ // fall through to the terminator branch below.
376
281
  const fieldHeadingMatch = line.match(/^#{2,3}\s+([\w-]+)\s*$/i);
377
282
  const fieldName = fieldHeadingMatch?.[1]?.toLowerCase().replace(/-/g, '_');
378
283
  if (HEADING_TO_FIELD.has(fieldName)) {
@@ -403,14 +308,9 @@ function splitSections(markdown) {
403
308
  }
404
309
 
405
310
  /**
406
- * True for a non-canonical markdown heading that TERMINATES the current
407
- * structured section. Trailing extended content a producer appends after the
408
- * canonical block — `audit-to-stories`'s `## Agent Prompts` / `## Context`
409
- * / `## Sequencing` blocks, for instance — must not bleed into the last
410
- * structured section's bullet list (Story #4270). Without this, those
411
- * lines were silently absorbed into `verify[]` / `acceptance[]`. The
412
- * heading and everything under it is dropped from structured parsing
413
- * (it is extended, non-canonical markdown).
311
+ * A non-canonical heading closes the current section so appended extended
312
+ * content (e.g. `## Agent Prompts`) never bleeds into `verify[]` /
313
+ * `acceptance[]`. Text-block sections keep their own headings.
414
314
  *
415
315
  * @param {string} line
416
316
  * @param {boolean} inPreamble
@@ -426,11 +326,6 @@ function isSectionTerminatorHeading(line, inPreamble, currentSection) {
426
326
  }
427
327
 
428
328
  /**
429
- * True for the legacy machine-managed marker lines section parsing skips
430
- * wherever they appear (see the regexes above): a `## References` section
431
- * immediately followed by a retired meta block must not swallow the comment
432
- * as a references entry.
433
- *
434
329
  * @param {string} line
435
330
  * @returns {boolean}
436
331
  */
@@ -442,19 +337,13 @@ function isMachineMarkerLine(line) {
442
337
  );
443
338
  }
444
339
 
445
- // ---------------------------------------------------------------------------
446
- // Parser — per-section sub-parsers
447
- // ---------------------------------------------------------------------------
448
-
449
340
  /**
450
- * Build the minimal {@link ParseResult} returned for an unstructured body —
451
- * markdown that carries no recognised structured section. The goal falls
452
- * back to the preamble text (or the whole trimmed input), `depends_on` is
453
- * still recovered from the footer, and all section arrays are empty.
341
+ * Minimal result for a body with no structured section: goal falls back to
342
+ * the preamble, `depends_on` is still read from the footer.
454
343
  *
455
- * @param {string} input - The original markdown string.
456
- * @param {string} preamble - Text before the first heading (from splitSections).
457
- * @param {string} footer - Footer block text (from splitSections).
344
+ * @param {string} input
345
+ * @param {string} preamble
346
+ * @param {string} footer
458
347
  * @returns {ParseResult}
459
348
  */
460
349
  function parseUnstructuredBody(input, preamble, footer) {
@@ -490,10 +379,7 @@ function parseUnstructuredBody(input, preamble, footer) {
490
379
  }
491
380
 
492
381
  /**
493
- * Parse the `## Goal` section: join its non-empty content lines into a
494
- * single one-line goal string.
495
- *
496
- * @param {string[]} lines - Raw content lines under the heading.
382
+ * @param {string[]} lines
497
383
  * @returns {string}
498
384
  */
499
385
  function parseGoalSection(lines) {
@@ -504,10 +390,8 @@ function parseGoalSection(lines) {
504
390
  }
505
391
 
506
392
  /**
507
- * Parse a verbatim text-block section (`## Slicing` or `## Spec`) into a
508
- * newline-joined string. Unlike {@link parseGoalSection}, line breaks are
509
- * preserved so a bullet list, compact table, or folded Tech Spec survives the
510
- * round-trip; only blank lines and trailing whitespace are normalized.
393
+ * Line breaks are preserved so lists and tables round-trip; only blank edge
394
+ * lines and trailing whitespace are normalized.
511
395
  *
512
396
  * @param {string[]} lines
513
397
  * @returns {string}
@@ -520,12 +404,8 @@ function parseTextBlockSection(lines) {
520
404
  }
521
405
 
522
406
  /**
523
- * Parse a `## Changes` / `## References` section into a list of
524
- * `PathEntry` entries. List markers are stripped, blank entries are
525
- * dropped, and each surviving entry is normalized via {@link parsePathEntry}.
526
- *
527
- * @param {string[]} lines - Raw content lines under the heading.
528
- * @param {string[]} warnings - Mutable warnings sink.
407
+ * @param {string[]} lines
408
+ * @param {string[]} warnings
529
409
  * @returns {PathEntry[]}
530
410
  */
531
411
  function parsePathEntrySection(lines, warnings) {
@@ -540,46 +420,17 @@ function parsePathEntrySection(lines, warnings) {
540
420
  }
541
421
 
542
422
  /**
543
- * Parse a plain bullet-list section (`## Acceptance` / `## Verify`) into a
544
- * list of trimmed strings, dropping blank entries.
545
- *
546
- * @param {string[]} lines - Raw content lines under the heading.
423
+ * @param {string[]} lines
547
424
  * @returns {string[]}
548
425
  */
549
426
  function parseTextListSection(lines) {
550
427
  return lines.map((l) => stripListMarker(l)).filter(Boolean);
551
428
  }
552
429
 
553
- // ---------------------------------------------------------------------------
554
- // Parser
555
- // ---------------------------------------------------------------------------
556
-
557
- /**
558
- * Parse a GitHub Story issue body (markdown string) into a structured
559
- * {@link StoryBody}. Fails closed on malformed input.
560
- *
561
- * Returns a {@link ParseResult} containing the body, any non-fatal
562
- * warnings, and parse metadata. Use `result.body` directly; inspect
563
- * `result.warnings` to detect legacy path entries that should be
564
- * migrated.
565
- *
566
- * @param {string|object} input - Markdown string or already-structured body object.
567
- * @returns {ParseResult}
568
- * @throws {StoryBodyParseError} When the body is structurally unrecoverable.
569
- */
570
430
  /**
571
- * Strip the presentation `AC-<n>:` handle off one acceptance item.
572
- *
573
- * The handle belongs to {@link serialize}, which numbers every checkbox from
574
- * its position in `acceptance[]`; an authored item that already carries one
575
- * would render doubled (`- [ ] AC-1: AC-1: …`) and a lettered handle copied
576
- * from a source ticket would survive into the machine contract. Both parse
577
- * and the persist-side normalisation resolve the grammar here so the two can
578
- * never disagree about what a handle is (Story #5323).
579
- *
580
- * Stacked handles are peeled in full — a body persisted while the doubling
581
- * was live carries two, and leaving the inner one would normalise to
582
- * something that still is not the authored text.
431
+ * Strip every stacked `AC-<n>:` handle. serialize() numbers checkboxes from
432
+ * position, so a kept handle would render doubled; parse and persist share
433
+ * this so they agree on the grammar.
583
434
  *
584
435
  * @param {string} item
585
436
  * @returns {{ text: string, stripped: boolean }} The handle-free text, and
@@ -594,6 +445,13 @@ export function stripAcceptanceHandle(item) {
594
445
  return { text, stripped: text !== original };
595
446
  }
596
447
 
448
+ /**
449
+ * Parse a Story issue body (markdown or structured object).
450
+ *
451
+ * @param {string|object} input - Markdown string or already-structured body object.
452
+ * @returns {ParseResult}
453
+ * @throws {StoryBodyParseError} When the body is structurally unrecoverable.
454
+ */
597
455
  export function parse(input) {
598
456
  if (input === null || input === undefined) {
599
457
  throw new StoryBodyParseError('Story body is null or undefined', {
@@ -601,8 +459,6 @@ export function parse(input) {
601
459
  });
602
460
  }
603
461
 
604
- // If the caller already has a structured object (e.g. from the decomposer
605
- // before it's serialized to markdown), parse it directly.
606
462
  if (typeof input === 'object' && !Array.isArray(input)) {
607
463
  return parseStructuredObject(input);
608
464
  }
@@ -626,7 +482,6 @@ export function parse(input) {
626
482
  const hasSlicingSection = sections.has('slicing');
627
483
  const hasSpecSection = sections.has('spec');
628
484
 
629
- // If no structured sections found, treat as unstructured body.
630
485
  const isUnstructuredBody =
631
486
  !hasGoalSection &&
632
487
  !hasChangesSection &&
@@ -638,19 +493,12 @@ export function parse(input) {
638
493
  }
639
494
 
640
495
  const goal = parseGoalSection(sections.get('goal') ?? []);
641
- // Optional v2 intra-Story delivery slice plan (`## Slicing`). Preserved as
642
- // a verbatim text block — a large Story (what v1 called an Epic) folds its
643
- // Delivery Slicing here instead of fanning out into sibling Stories; a
644
- // trivial Story omits it entirely. Parsed as a text block so a bullet list
645
- // or compact table round-trips.
646
496
  const slicing = parseTextBlockSection(sections.get('slicing') ?? []);
647
497
  const spec = parseTextBlockSection(sections.get('spec') ?? []);
648
498
  const changes = parsePathEntrySection(
649
499
  sections.get('changes') ?? [],
650
500
  warnings,
651
501
  );
652
- // The AC-<n> checkbox prefix is presentation-only (Story #4600): strip it
653
- // so acceptance[] round-trips byte-identical to the authored array.
654
502
  const acceptance = parseTextListSection(sections.get('acceptance') ?? []).map(
655
503
  (a) => stripAcceptanceHandle(a).text,
656
504
  );
@@ -692,9 +540,7 @@ export function parse(input) {
692
540
  }
693
541
 
694
542
  /**
695
- * Parse a structured body object (as produced by the decomposer's JSON
696
- * output, before markdown serialization). Normalizes all fields to the
697
- * canonical shape.
543
+ * Normalize a structured body object (pre-serialization decomposer output).
698
544
  *
699
545
  * @param {object} obj
700
546
  * @returns {ParseResult}
@@ -702,10 +548,6 @@ export function parse(input) {
702
548
  function parseStructuredObject(obj) {
703
549
  const warnings = [];
704
550
 
705
- // The declarative half of the normalization: every field whose value is a
706
- // pure function of its raw input (plus the shared warnings sink) is one
707
- // table row, walked in canonical body-key order. Adding a field of an
708
- // existing kind is a one-row change.
709
551
  const body = {};
710
552
  for (const { name, kind } of STRUCTURED_FIELD_SPECS) {
711
553
  body[name] = STRUCTURED_FIELD_NORMALIZERS[kind](obj[name], warnings);
@@ -729,36 +571,23 @@ function parseStructuredObject(obj) {
729
571
  }
730
572
 
731
573
  /**
732
- * The field-spec table driving {@link parseStructuredObject}, in canonical
733
- * body-key order. `kind` selects the normalizer from
734
- * {@link STRUCTURED_FIELD_NORMALIZERS}:
735
- * - `text` — trimmed string, or `''` when absent/non-string.
736
- * - `stringList` — array filtered to non-empty strings, else `[]`.
737
- * - `pathEntryList` — array normalized entry-wise via `parsePathEntry`
738
- * (fails closed on a malformed entry), else `[]`.
574
+ * Field specs in canonical body-key order.
739
575
  *
740
576
  * @type {Array<{ name: string, kind: keyof typeof STRUCTURED_FIELD_NORMALIZERS }>}
741
577
  */
742
578
  const STRUCTURED_FIELD_SPECS = [
743
579
  { name: 'goal', kind: 'text' },
744
- // slicing — optional v2 intra-Story delivery slice plan (verbatim text).
745
580
  { name: 'slicing', kind: 'text' },
746
- // spec — optional folded Tech Spec (verbatim text).
747
581
  { name: 'spec', kind: 'text' },
748
582
  { name: 'changes', kind: 'pathEntryList' },
749
583
  { name: 'acceptance', kind: 'stringList' },
750
584
  { name: 'verify', kind: 'stringList' },
751
585
  { name: 'references', kind: 'pathEntryList' },
752
- // non_goals — advisory negative-scope bullets.
753
586
  { name: 'non_goals', kind: 'stringList' },
754
- // depends_on — may be at top level or in body.
755
587
  { name: 'depends_on', kind: 'stringList' },
756
588
  ];
757
589
 
758
590
  /**
759
- * One normalizer per {@link STRUCTURED_FIELD_SPECS} kind. Each takes the raw
760
- * field value plus the shared warnings sink and returns the canonical value.
761
- *
762
591
  * @type {Record<string, (raw: unknown, warnings: string[]) => unknown>}
763
592
  */
764
593
  const STRUCTURED_FIELD_NORMALIZERS = {
@@ -777,34 +606,19 @@ const STRUCTURED_FIELD_NORMALIZERS = {
777
606
  },
778
607
  };
779
608
 
780
- // ---------------------------------------------------------------------------
781
- // Serializer
782
- // ---------------------------------------------------------------------------
783
-
784
609
  /**
785
- * Render a `PathEntry | string` as a markdown list item.
786
- *
787
610
  * @param {PathEntry | string} entry
788
611
  * @returns {string}
789
612
  */
790
613
  function serializePathEntry(entry) {
791
614
  if (typeof entry === 'string') return entry;
792
- // Canonical object form (Story #4600): render as a human-readable bullet —
793
- // path in backticks, em-dash, assumption. parsePathEntry recognizes this
794
- // shape (and the legacy inline-JSON shape) for round-trip fidelity.
795
- return `\`${entry.path}\` — ${entry.assumption}`;
615
+ // A bare entry (no assumption) stays bare; persist derives the assumption.
616
+ return [`\`${entry.path}\``, entry.assumption].filter(Boolean).join(' — ');
796
617
  }
797
618
 
798
619
  /**
799
- * Descriptor table for the human-readable Story-body sections, in canonical
800
- * emit order (`## Goal`, `## Slicing`, `## Spec`, `## Changes`,
801
- * `## Acceptance`, `## Verify`, `## References`, `## Non-Goals`). Each
802
- * descriptor reads one body field and returns the section's markdown block
803
- * when the field is present and non-empty, or `null` to omit the section.
804
- *
805
- * Standardising the section ladder as a single data table makes adding a new
806
- * optional section a one-line edit here rather than a new control-flow branch
807
- * in {@link serialize}.
620
+ * Sections in canonical emit order; `render` returns `null` to omit, so an
621
+ * absent optional field keeps older bodies round-tripping byte-identically.
808
622
  *
809
623
  * @type {Array<{ field: string, render: (value: unknown) => string | null }>}
810
624
  */
@@ -817,10 +631,6 @@ const SERIALIZE_SECTIONS = [
817
631
  : null,
818
632
  },
819
633
  {
820
- // Optional v2 intra-Story delivery slice plan. Single-token `## Slicing`
821
- // heading (recognized by the `[\w-]+` field-heading regex). Verbatim text
822
- // block. Render-when-non-empty: an absent/empty `slicing` emits nothing,
823
- // so every pre-v2 body round-trips byte-identically.
824
634
  field: 'slicing',
825
635
  render: (slicing) =>
826
636
  typeof slicing === 'string' && slicing.trim().length > 0
@@ -828,8 +638,6 @@ const SERIALIZE_SECTIONS = [
828
638
  : null,
829
639
  },
830
640
  {
831
- // Optional folded Tech Spec. Like `## Slicing`, this is a verbatim text
832
- // block and emits nothing for absent/empty pre-v2 bodies.
833
641
  field: 'spec',
834
642
  render: (spec) =>
835
643
  typeof spec === 'string' && spec.trim().length > 0
@@ -844,10 +652,6 @@ const SERIALIZE_SECTIONS = [
844
652
  : null,
845
653
  },
846
654
  {
847
- // Each checkbox carries a stable 1-based `AC-<n>:` handle (Story #4600)
848
- // so humans and reviewers can reference criteria by number. The prefix
849
- // is presentation-only — parse() strips it, and validators compare the
850
- // top-level acceptance[] array, so numbering never affects gating.
851
655
  field: 'acceptance',
852
656
  render: (acceptance) =>
853
657
  Array.isArray(acceptance) && acceptance.length > 0
@@ -869,11 +673,6 @@ const SERIALIZE_SECTIONS = [
869
673
  : null,
870
674
  },
871
675
  {
872
- // Advisory negative-scope bullets. Rendered as the hyphenated canonical
873
- // `## Non-Goals` heading (the spelling the parser's widened
874
- // `[\w-]+` field-heading regex recognizes). Render-when-non-empty: an
875
- // empty or absent `non_goals` emits nothing, so every pre-existing body
876
- // round-trips byte-identically.
877
676
  field: 'non_goals',
878
677
  render: (nonGoals) =>
879
678
  Array.isArray(nonGoals) && nonGoals.length > 0
@@ -883,9 +682,6 @@ const SERIALIZE_SECTIONS = [
883
682
  ];
884
683
 
885
684
  /**
886
- * Build the optional `---` footer block (`parent` / `blocked by` lines).
887
- * Returns the empty string when `opts.includeFooter` is falsy.
888
- *
889
685
  * @param {StoryBody} body
890
686
  * @param {SerializeOptions} opts
891
687
  * @returns {string}
@@ -894,9 +690,7 @@ function serializeFooter(body, opts) {
894
690
  if (!opts.includeFooter) return '';
895
691
  const footerLines = ['---'];
896
692
  if (opts.footer?.parent) footerLines.push(`parent: #${opts.footer.parent}`);
897
- // Story #4545 — no `Epic: #N` branch. `pr-base-guard.js` hard-refuses a
898
- // Story body carrying that footer, so composing one here would let the
899
- // framework generate work it would then reject at delivery.
693
+ // Never an `Epic: #N` line: pr-base-guard.js refuses a body carrying one.
900
694
  if (Array.isArray(body.depends_on)) {
901
695
  for (const dep of body.depends_on) {
902
696
  footerLines.push(`blocked by ${dep}`);
@@ -906,13 +700,6 @@ function serializeFooter(body, opts) {
906
700
  }
907
701
 
908
702
  /**
909
- * Serialize a structured {@link StoryBody} back to the canonical markdown
910
- * format written to GitHub issue bodies.
911
- *
912
- * The output matches the section order the spec-renderer uses:
913
- * `## Goal`, `## Slicing`, `## Spec`, `## Changes`, `## Acceptance`,
914
- * `## Verify`, `## References`, `## Non-Goals` (each omitted when empty).
915
- *
916
703
  * @param {StoryBody} body
917
704
  * @param {SerializeOptions} [opts]
918
705
  * @returns {string}
@@ -933,17 +720,9 @@ export function serialize(body, opts = {}) {
933
720
  return sections.join('\n\n') + serializeFooter(body, opts);
934
721
  }
935
722
 
936
- // ---------------------------------------------------------------------------
937
- // Convenience: extract changes paths for the wave planner
938
- // ---------------------------------------------------------------------------
939
-
940
723
  /**
941
- * Extract the list of path strings from a parsed `changes[]` array.
942
- * Glob-bearing entries are flagged via `{ path, isGlob: true }`.
943
- *
944
- * The wave planner (Feature 3) uses this to compute file-overlap
945
- * serialization between Stories: if any entry `isGlob`, the Story's
946
- * footprint is `unknown-width`.
724
+ * Path strings from `changes[]`; any glob entry makes the footprint
725
+ * unknown-width for the wave planner.
947
726
  *
948
727
  * @param {ChangeEntry[]} changes
949
728
  * @returns {Array<{ path: string, isGlob: boolean }>}