mandrel 1.93.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/acceptance-critic.md +129 -0
  3. package/.agents/agents/story-worker.md +161 -0
  4. package/.agents/docs/SDLC.md +489 -1285
  5. package/.agents/docs/agentrc-reference.json +177 -67
  6. package/.agents/docs/configuration.md +108 -136
  7. package/.agents/docs/execution-reference.md +44 -22
  8. package/.agents/docs/quality-gates.md +13 -19
  9. package/.agents/docs/workflows.md +3 -3
  10. package/.agents/instructions.md +107 -108
  11. package/.agents/rules/ci-remediation.md +8 -12
  12. package/.agents/rules/git-conventions-reference.md +224 -0
  13. package/.agents/rules/git-conventions.md +42 -223
  14. package/.agents/rules/security-baseline.md +5 -0
  15. package/.agents/rules/testing-standards.md +106 -13
  16. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  17. package/.agents/schemas/agentrc.schema.json +71 -201
  18. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  20. package/.agents/schemas/risk-verdict.schema.json +0 -13
  21. package/.agents/scripts/acceptance-eval.js +62 -18
  22. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  23. package/.agents/scripts/analyze-execution.js +1 -1
  24. package/.agents/scripts/audit-to-stories.js +7 -7
  25. package/.agents/scripts/boot-sweep.js +1 -1
  26. package/.agents/scripts/check-context-budget.js +62 -5
  27. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  28. package/.agents/scripts/check-prepush-recovery.js +1 -1
  29. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  30. package/.agents/scripts/diagnose-friction.js +0 -6
  31. package/.agents/scripts/lib/Logger.js +6 -10
  32. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  33. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  34. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  35. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  36. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  37. package/.agents/scripts/lib/baselines/reader.js +1 -6
  38. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  39. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  40. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
  41. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  42. package/.agents/scripts/lib/checks/index.js +2 -1
  43. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  44. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  45. package/.agents/scripts/lib/cli-args.js +16 -7
  46. package/.agents/scripts/lib/close-validation/gates.js +160 -22
  47. package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
  48. package/.agents/scripts/lib/config/ci.js +6 -31
  49. package/.agents/scripts/lib/config/delivery-routing.js +103 -0
  50. package/.agents/scripts/lib/config/explain.js +57 -36
  51. package/.agents/scripts/lib/config/limits.js +17 -58
  52. package/.agents/scripts/lib/config/paths.js +0 -2
  53. package/.agents/scripts/lib/config/quality.js +1 -1
  54. package/.agents/scripts/lib/config/runners.js +17 -50
  55. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  56. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  57. package/.agents/scripts/lib/config-resolver.js +3 -8
  58. package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
  59. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
  60. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  61. package/.agents/scripts/lib/dependency-parser.js +3 -2
  62. package/.agents/scripts/lib/doc-tiers.js +39 -4
  63. package/.agents/scripts/lib/duplicate-search.js +211 -41
  64. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  65. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  66. package/.agents/scripts/lib/framework-version.js +2 -3
  67. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  68. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  69. package/.agents/scripts/lib/git-utils.js +32 -6
  70. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  71. package/.agents/scripts/lib/label-constants.js +10 -23
  72. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  73. package/.agents/scripts/lib/observability/active-story-env.js +112 -3
  74. package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
  75. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  76. package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
  77. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  78. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
  79. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
  80. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  81. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
  82. package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
  83. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  84. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  85. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  86. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  87. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  88. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  89. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  90. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  91. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  92. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  93. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  94. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  95. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  96. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  97. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  98. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
  99. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  100. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  101. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  102. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  103. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  104. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  105. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  106. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  107. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  108. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
  109. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  110. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  111. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  112. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  113. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  114. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  115. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  116. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  117. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  118. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  119. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  120. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  121. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  122. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  123. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  124. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  126. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  130. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  131. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  132. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  133. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  134. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  135. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  136. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  137. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  138. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  139. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  140. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  141. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  142. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  143. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  144. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  145. package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
  146. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  147. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  148. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  149. package/.agents/scripts/lib/planning-corpus.js +16 -11
  150. package/.agents/scripts/lib/preflight-runner.js +2 -2
  151. package/.agents/scripts/lib/provider-factory.js +1 -1
  152. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  153. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  154. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  155. package/.agents/scripts/lib/story-adjacency.js +11 -14
  156. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  157. package/.agents/scripts/lib/story-plan.js +2 -4
  158. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  159. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  160. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  161. package/.agents/scripts/lib/validation-evidence.js +1 -1
  162. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  163. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  164. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  165. package/.agents/scripts/lint-issue-body.js +71 -40
  166. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  167. package/.agents/scripts/notify.js +4 -3
  168. package/.agents/scripts/plan-context.js +64 -74
  169. package/.agents/scripts/plan-persist.js +121 -280
  170. package/.agents/scripts/plan-run-epilogue.js +97 -0
  171. package/.agents/scripts/post-structured-comment.js +38 -0
  172. package/.agents/scripts/providers/github/issues.js +17 -33
  173. package/.agents/scripts/providers/github/mappers.js +0 -12
  174. package/.agents/scripts/providers/github/tickets.js +2 -5
  175. package/.agents/scripts/resolve-plan-run.js +117 -0
  176. package/.agents/scripts/signals-view.js +24 -19
  177. package/.agents/scripts/single-story-close.js +11 -14
  178. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  179. package/.agents/scripts/single-story-init.js +29 -20
  180. package/.agents/scripts/stories-wave-tick.js +6 -6
  181. package/.agents/scripts/story-plan.js +26 -47
  182. package/.agents/scripts/sync-claude-agents.js +165 -0
  183. package/.agents/scripts/update-ticket-state.js +37 -15
  184. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  185. package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
  186. package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
  187. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
  188. package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
  189. package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
  190. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
  191. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  192. package/.agents/skills/skills.index.json +8 -418
  193. package/.agents/starter-agentrc.json +0 -5
  194. package/.agents/templates/agent-protocol.md +9 -10
  195. package/.agents/workflows/audit-architecture.md +3 -3
  196. package/.agents/workflows/audit-clean-code.md +3 -3
  197. package/.agents/workflows/audit-dependencies.md +3 -3
  198. package/.agents/workflows/audit-devops.md +3 -3
  199. package/.agents/workflows/audit-documentation.md +5 -5
  200. package/.agents/workflows/audit-lighthouse.md +3 -3
  201. package/.agents/workflows/audit-navigability.md +3 -2
  202. package/.agents/workflows/audit-performance.md +3 -3
  203. package/.agents/workflows/audit-privacy.md +3 -3
  204. package/.agents/workflows/audit-quality.md +3 -3
  205. package/.agents/workflows/audit-security.md +3 -3
  206. package/.agents/workflows/audit-seo.md +3 -3
  207. package/.agents/workflows/audit-sre.md +3 -3
  208. package/.agents/workflows/audit-to-stories.md +20 -20
  209. package/.agents/workflows/audit-ux-ui.md +3 -3
  210. package/.agents/workflows/deliver.md +122 -131
  211. package/.agents/workflows/git-cleanup.md +3 -4
  212. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  213. package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
  214. package/.agents/workflows/helpers/code-review.md +70 -193
  215. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  216. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  217. package/.agents/workflows/helpers/diagnose.md +10 -10
  218. package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
  219. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  220. package/.agents/workflows/helpers/signals.md +16 -16
  221. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  222. package/.agents/workflows/mandrel-update.md +3 -2
  223. package/.agents/workflows/plan.md +112 -145
  224. package/.agents/workflows/qa-assist.md +24 -30
  225. package/.agents/workflows/qa-explore.md +29 -38
  226. package/.agents/workflows/qa-run.md +2 -2
  227. package/README.md +9 -8
  228. package/docs/CHANGELOG.md +46 -0
  229. package/lib/cli/registry.js +95 -0
  230. package/lib/migrations/index.js +6 -5
  231. package/package.json +5 -3
  232. package/.agents/personas/architect.md +0 -113
  233. package/.agents/personas/devops-engineer.md +0 -38
  234. package/.agents/personas/engineer-mobile.md +0 -120
  235. package/.agents/personas/engineer-web.md +0 -111
  236. package/.agents/personas/engineer.md +0 -119
  237. package/.agents/personas/product.md +0 -94
  238. package/.agents/personas/project-manager.md +0 -114
  239. package/.agents/personas/qa-engineer.md +0 -95
  240. package/.agents/personas/refactorer.md +0 -113
  241. package/.agents/personas/security-engineer.md +0 -112
  242. package/.agents/personas/sre.md +0 -86
  243. package/.agents/personas/technical-writer.md +0 -101
  244. package/.agents/personas/ux-designer.md +0 -95
  245. package/.agents/schemas/dispatch-manifest.json +0 -232
  246. package/.agents/schemas/epic-spec.schema.json +0 -153
  247. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  248. package/.agents/scripts/dispatcher.js +0 -295
  249. package/.agents/scripts/epic-audit-prepare.js +0 -497
  250. package/.agents/scripts/epic-audit-recheck.js +0 -274
  251. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  252. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  253. package/.agents/scripts/epic-deliver-prepare.js +0 -590
  254. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  255. package/.agents/scripts/epic-plan-clarity.js +0 -211
  256. package/.agents/scripts/epic-plan-decompose.js +0 -54
  257. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  258. package/.agents/scripts/epic-plan-spec.js +0 -64
  259. package/.agents/scripts/epic-reconcile.js +0 -625
  260. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  261. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  262. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  263. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  264. package/.agents/scripts/lib/config/preflight.js +0 -58
  265. package/.agents/scripts/lib/config/retro.js +0 -77
  266. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  267. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  268. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  269. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
  270. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  271. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  272. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  273. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  274. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  275. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  276. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  277. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  278. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  279. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  280. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  281. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  282. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  283. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  284. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  285. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  286. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  287. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  288. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
  289. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  290. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  291. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  292. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  293. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  294. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  295. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  296. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  297. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  298. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  299. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  300. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  301. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  302. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  303. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  304. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  305. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  306. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  307. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  308. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  309. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  310. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  311. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  313. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
  314. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  315. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  316. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  317. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
  318. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  319. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  320. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  321. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  322. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  323. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  324. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  325. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  326. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  327. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  328. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  329. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  330. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  331. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  332. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  333. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  334. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  335. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
  336. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  337. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  338. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  339. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  340. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  341. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  342. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  343. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  344. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  345. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  346. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  347. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  348. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  349. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  350. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  351. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  352. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  353. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  354. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  355. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  356. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  357. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  358. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  359. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  360. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  361. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
  362. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  363. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  364. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  365. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  366. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  367. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  368. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  369. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  370. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  371. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  372. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  373. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  374. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  375. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  376. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  377. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  378. package/.agents/scripts/lib/spec/index.js +0 -36
  379. package/.agents/scripts/lib/spec/loader.js +0 -425
  380. package/.agents/scripts/lib/spec/state.js +0 -208
  381. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  382. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  383. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  384. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  385. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  386. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  387. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  388. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  389. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  390. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  391. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  392. package/.agents/scripts/lifecycle-emit.js +0 -510
  393. package/.agents/scripts/plan-critics.js +0 -199
  394. package/.agents/scripts/retro-run.js +0 -218
  395. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  396. package/.agents/scripts/story-close.js +0 -294
  397. package/.agents/scripts/story-init.js +0 -599
  398. package/.agents/scripts/story-phase.js +0 -369
  399. package/.agents/scripts/wave-tick.js +0 -335
  400. package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
  401. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
  402. package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
  403. package/.agents/skills/core/code-simplification/SKILL.md +0 -389
  404. package/.agents/skills/core/context-engineering/SKILL.md +0 -309
  405. package/.agents/skills/core/context-engineering/examples.md +0 -58
  406. package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
  407. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  408. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  409. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  410. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  411. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  412. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  413. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
  414. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  415. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
  416. package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
  417. package/.agents/skills/core/idea-refinement/examples.md +0 -437
  418. package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
  419. package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
  420. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
  421. package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
  422. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
  423. package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
  424. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
  425. package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
  426. package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
  427. package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
  428. package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
  429. package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
  430. package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
  431. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
  432. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
  433. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
  434. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
  435. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
  436. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
  437. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
  438. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
  439. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
  440. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
  441. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
  442. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
  443. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
  444. package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
  445. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
  446. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
  447. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
  448. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
  449. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
  450. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
  451. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
  452. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
  453. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
  454. package/.agents/workflows/helpers/deliver-epic.md +0 -955
  455. package/.agents/workflows/helpers/deliver-stories.md +0 -440
  456. package/.agents/workflows/helpers/epic-audit.md +0 -189
  457. package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
  458. package/.agents/workflows/helpers/epic-testing.md +0 -125
  459. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  460. package/.agents/workflows/helpers/plan-epic.md +0 -351
  461. package/.agents/workflows/helpers/plan-story.md +0 -251
  462. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  463. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -1,447 +0,0 @@
1
- /**
2
- * lib/orchestration/spec-renderer.js — tickets.json → epic-spec.yaml
3
- * projection (2-tier shape, Story #4041).
4
- *
5
- * The decomposer (`epic-plan-decompose-author`) produces a flat array
6
- * of Story ticket objects keyed by stable `slug`s and linked by
7
- * `depends_on`. The spec reconciler consumes the declarative
8
- * structural representation defined by
9
- * `.agents/schemas/epic-spec.schema.json` — a flat
10
- * `{ epic, stories: [...] }` shape with Story-level `wave`,
11
- * `dependsOn`, and inline `acceptance[]` / `verify[]` arrays
12
- * projected from the decomposer's edges.
13
- *
14
- * Under the 2-tier hierarchy (Story #4041), Stories have no Feature
15
- * parent and no Task children — acceptance and verify steps live
16
- * inline on the Story, and Stories attach directly to the Epic. Any
17
- * `feature` or `task` ticket in the decomposer input is rejected at
18
- * index time (hard cutover; see `.agents/rules/git-conventions.md` §
19
- * "Contract Cutovers — No Shim Layer").
20
- *
21
- * `renderSpec(tickets, opts)` is the pure projection between those
22
- * two shapes. It:
23
- *
24
- * 1. Indexes the flat array by slug. Any unrecognised type
25
- * (including the historical `feature` / `task`) raises
26
- * immediately.
27
- * 2. Filters Story `depends_on` edges down to inter-Story
28
- * references in the same Epic.
29
- * 3. Layers Stories into waves via `Graph.assignLayers` (depth in
30
- * the story-only DAG = wave index). Stories with no inbound
31
- * edges sit at `wave: 0`, matching the wave-runner's runtime
32
- * convention (`build-wave-dag.js` produces the same layering at
33
- * dispatch time from the live GH state, so the spec's waves are
34
- * observationally identical to what dispatch will compute).
35
- * 4. Walks the Stories in decomposer-declared order, preserving
36
- * the order the LLM emitted so the reconciler's diff stays
37
- * human-readable.
38
- * 5. Strips `agent::*` labels from every entity. The decomposer
39
- * doesn't normally write them, but they can leak via reverse-
40
- * bootstrap from live GH state — and the schema forbids them
41
- * (the reconciler explicitly enforces the structural/agent
42
- * label split).
43
- * 6. Projects each Story's inline `acceptance[]` / `verify[]`
44
- * arrays onto the rendered Story. The decomposer may emit
45
- * these either at the top level of the ticket (preferred) or
46
- * nested under a structured `body` object — the renderer reads
47
- * both and prefers the top-level fields when present.
48
- * 7. Validates the produced object against the spec schema before
49
- * returning. A renderer bug that emits a malformed spec is
50
- * caught synchronously rather than failing later in `loadSpec`.
51
- *
52
- * Pure — no I/O. The validator is compiled once per process and
53
- * cached by absolute schema path (same cache the loader uses
54
- * internally; this module re-derives the path from its own location
55
- * so the renderer imposes no new resolution surface).
56
- *
57
- * Round-trip: parse a tickets fixture → render → write to YAML →
58
- * reload via `loadSpec` → the reloaded shape is structurally
59
- * identical to the renderer output (modulo YAML's omission of
60
- * `undefined` keys). Verified by `tests/scripts/spec-renderer.test.js`.
61
- */
62
-
63
- import { existsSync, readFileSync } from 'node:fs';
64
- import path from 'node:path';
65
- import { fileURLToPath } from 'node:url';
66
- import Ajv2020 from 'ajv/dist/2020.js';
67
- import addFormats from 'ajv-formats';
68
- import { assignLayers } from '../Graph.js';
69
-
70
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
71
-
72
- // scripts/lib/orchestration/ → scripts/lib/ → scripts/ → .agents/
73
- const DEFAULT_SCHEMA_PATH = path.resolve(
74
- __dirname,
75
- '..',
76
- '..',
77
- '..',
78
- 'schemas',
79
- 'epic-spec.schema.json',
80
- );
81
-
82
- const AGENT_LABEL_PREFIX = 'agent::';
83
-
84
- let cachedValidator = null;
85
- let cachedValidatorKey = null;
86
-
87
- function getValidator(schemaPath) {
88
- if (cachedValidator && cachedValidatorKey === schemaPath) {
89
- return cachedValidator;
90
- }
91
- const ajv = new Ajv2020({ allErrors: true, strict: false });
92
- addFormats(ajv);
93
- const schema = JSON.parse(readFileSync(schemaPath, 'utf8'));
94
- cachedValidator = ajv.compile(schema);
95
- cachedValidatorKey = schemaPath;
96
- return cachedValidator;
97
- }
98
-
99
- /**
100
- * Test-only hook: drop the cached validator so a subsequent call
101
- * recompiles. The renderer reuses one Ajv instance per process for
102
- * cost reasons; tests that swap to a sandbox schema must reset it.
103
- */
104
- export function _resetRendererValidatorCacheForTests() {
105
- cachedValidator = null;
106
- cachedValidatorKey = null;
107
- }
108
-
109
- /**
110
- * Raised when the rendered spec object fails schema validation. The
111
- * Ajv errors are normalised to `{ path, message }` so callers can
112
- * report the offending JSON Pointer without unwrapping Ajv's envelope.
113
- */
114
- export class SpecRenderValidationError extends Error {
115
- /**
116
- * @param {Array<{path: string, message: string, params?: object}>} issues
117
- */
118
- constructor(issues) {
119
- const head = issues[0] ?? { path: '/', message: 'unknown' };
120
- super(
121
- `Rendered spec failed schema validation at ${head.path}: ${head.message}`,
122
- );
123
- this.name = 'SpecRenderValidationError';
124
- this.issues = issues;
125
- }
126
- }
127
-
128
- function normaliseAjvErrors(ajvErrors) {
129
- return ajvErrors.map((err) => {
130
- let p = err.instancePath || '/';
131
- if (
132
- err.keyword === 'required' &&
133
- typeof err.params?.missingProperty === 'string'
134
- ) {
135
- const sep = p === '/' ? '' : '/';
136
- p = `${p}${sep}${err.params.missingProperty}`;
137
- }
138
- return {
139
- path: p,
140
- message: err.message ?? 'validation failed',
141
- params: err.params,
142
- };
143
- });
144
- }
145
-
146
- function sanitizeLabels(labels) {
147
- if (!Array.isArray(labels)) return undefined;
148
- const out = [];
149
- const seen = new Set();
150
- for (const raw of labels) {
151
- if (typeof raw !== 'string' || raw.length === 0) continue;
152
- if (raw.startsWith(AGENT_LABEL_PREFIX)) continue;
153
- if (seen.has(raw)) continue;
154
- seen.add(raw);
155
- out.push(raw);
156
- }
157
- return out.length > 0 ? out : undefined;
158
- }
159
-
160
- /**
161
- * Descriptor table for the structured-body → markdown projection, in
162
- * canonical emit order (`## Goal`, `## Changes`, `## Acceptance`,
163
- * `## Verify`). Each descriptor reads one body field and returns the
164
- * section's markdown block when the field is present and non-empty, or `null`
165
- * to omit it. Adding a section is a one-line data edit rather than a new
166
- * branch in {@link renderBody}.
167
- *
168
- * @type {Array<{ field: string, render: (value: unknown) => string | null }>}
169
- */
170
- const SPEC_BODY_SECTIONS = [
171
- {
172
- field: 'goal',
173
- render: (goal) =>
174
- typeof goal === 'string' && goal.length > 0 ? `## Goal\n${goal}` : null,
175
- },
176
- {
177
- field: 'changes',
178
- render: (changes) =>
179
- Array.isArray(changes) && changes.length > 0
180
- ? `## Changes\n${changes.map((c) => `- ${String(c)}`).join('\n')}`
181
- : null,
182
- },
183
- {
184
- field: 'acceptance',
185
- render: (acceptance) =>
186
- Array.isArray(acceptance) && acceptance.length > 0
187
- ? `## Acceptance\n${acceptance.map((a) => `- [ ] ${String(a)}`).join('\n')}`
188
- : null,
189
- },
190
- {
191
- field: 'verify',
192
- render: (verify) =>
193
- Array.isArray(verify) && verify.length > 0
194
- ? `## Verify\n${verify.map((v) => `- ${String(v)}`).join('\n')}`
195
- : null,
196
- },
197
- ];
198
-
199
- /**
200
- * Convert a decomposer body value into a spec `body` string. The
201
- * decomposer schema admits two shapes for a Story body:
202
- *
203
- * - A short string (preferred under the 2-tier hierarchy).
204
- * - A structured object (`{ goal, changes[], acceptance[],
205
- * verify[] }`) carried over from the legacy 4-tier Task body
206
- * shape, when the decomposer chooses to inline the Story's
207
- * Goal/Changes alongside its acceptance/verify arrays.
208
- *
209
- * The spec schema only models `body` as a string. For structured
210
- * bodies, render a compact markdown projection that preserves the
211
- * original sections so the reconciler's downstream issue-body apply
212
- * produces the same body the executing agent reads. For string
213
- * bodies, pass through unchanged. `undefined` / empty values drop
214
- * the field (the schema allows omission).
215
- *
216
- * The renderer does NOT round-trip structured bodies — by design,
217
- * the spec is the canonical surface once it's authored, and
218
- * structured bodies collapse into the markdown form on first
219
- * projection.
220
- *
221
- * @param {unknown} body
222
- * @returns {string | undefined}
223
- */
224
- function renderBody(body) {
225
- if (body == null) return undefined;
226
- if (typeof body === 'string') {
227
- return body.length > 0 ? body : undefined;
228
- }
229
- if (typeof body !== 'object') return undefined;
230
-
231
- const sections = [];
232
- for (const descriptor of SPEC_BODY_SECTIONS) {
233
- const block = descriptor.render(body[descriptor.field]);
234
- if (block !== null) sections.push(block);
235
- }
236
- return sections.length > 0 ? sections.join('\n\n') : undefined;
237
- }
238
-
239
- function assignNonEmpty(target, key, value) {
240
- if (value === undefined) return;
241
- target[key] = value;
242
- }
243
-
244
- /**
245
- * Index the flat ticket array by slug. Returns the ordered Story slug
246
- * list alongside the lookup map so the renderer can walk Stories in
247
- * the decomposer's emit order.
248
- *
249
- * Under the 2-tier hierarchy (Story #4041), only the `story` type is
250
- * recognised. Any other type — including the historical `feature` /
251
- * `task` — falls through to the unknown-type guard and raises
252
- * immediately; there is no silent drop.
253
- *
254
- * @param {Array<object>} tickets
255
- */
256
- function indexTickets(tickets) {
257
- const bySlug = new Map();
258
- const storySlugs = [];
259
-
260
- for (const t of tickets) {
261
- if (!t || typeof t !== 'object') continue;
262
- const slug = t.slug;
263
- if (typeof slug !== 'string' || slug.length === 0) {
264
- throw new Error(
265
- `[spec-renderer] ticket missing slug: ${JSON.stringify(t).slice(0, 120)}`,
266
- );
267
- }
268
- if (bySlug.has(slug)) {
269
- throw new Error(`[spec-renderer] duplicate slug "${slug}"`);
270
- }
271
- bySlug.set(slug, t);
272
- if (t.type === 'story') storySlugs.push(slug);
273
- else {
274
- throw new Error(
275
- `[spec-renderer] ticket "${slug}" has unknown type "${t.type}"`,
276
- );
277
- }
278
- }
279
- return { bySlug, storySlugs };
280
- }
281
-
282
- /**
283
- * Build the slug-keyed story dependency graph used for wave layering.
284
- * Drops every edge that does not reference another story slug in the
285
- * same Epic (defensive — Story slugs that were typo'd or self-edges
286
- * collapse here rather than polluting the wave count).
287
- *
288
- * @returns {{adjacency: Map<string, string[]>, layers: Map<string, number>}}
289
- */
290
- function layerStories(storySlugs, bySlug) {
291
- const storySet = new Set(storySlugs);
292
- const adjacency = new Map();
293
- for (const slug of storySlugs) {
294
- const story = bySlug.get(slug);
295
- const deps = Array.isArray(story.depends_on) ? story.depends_on : [];
296
- const filtered = deps.filter((d) => storySet.has(d) && d !== slug);
297
- adjacency.set(slug, filtered);
298
- }
299
- const layers = assignLayers(adjacency);
300
- return { adjacency, layers };
301
- }
302
-
303
- /**
304
- * Project the decomposer ticket array into the structural spec object.
305
- *
306
- * @param {Array<object>} tickets — flat ticket array as emitted by the
307
- * decomposer Skill (`type` = story, `slug`, `depends_on`, `title`,
308
- * `body`, `labels`, `acceptance`, `verify`).
309
- * @param {object} opts
310
- * @param {{id: number, title: string, body?: string, labels?: string[]}} opts.epic
311
- * — Epic descriptor (the decomposer doesn't emit the Epic row; it's
312
- * supplied by the caller, which has the live Epic ticket in hand).
313
- * @param {{baseline?: string, config?: string}} [opts.gates]
314
- * — Optional gates section, passed through verbatim into the spec.
315
- * @param {string} [opts.schemaPath] — override for the schema path
316
- * (tests).
317
- * @param {boolean} [opts.validate=true] — when `false`, skip final
318
- * schema validation (used by tests that intentionally craft invalid
319
- * inputs).
320
- * @returns {object} spec — `{ epic, stories, gates? }` matching
321
- * `.agents/schemas/epic-spec.schema.json`.
322
- */
323
- function validateRenderSpecInputs(tickets, opts) {
324
- if (!Array.isArray(tickets)) {
325
- throw new TypeError('[spec-renderer] tickets must be an array');
326
- }
327
- if (!opts || typeof opts !== 'object' || !opts.epic) {
328
- throw new TypeError('[spec-renderer] opts.epic is required');
329
- }
330
- const epic = opts.epic;
331
- if (!Number.isInteger(epic.id) || epic.id < 1) {
332
- throw new TypeError(
333
- '[spec-renderer] opts.epic.id must be a positive integer',
334
- );
335
- }
336
- if (typeof epic.title !== 'string' || epic.title.length === 0) {
337
- throw new TypeError('[spec-renderer] opts.epic.title must be a string');
338
- }
339
- }
340
-
341
- function pickStringArray(primary, fallback) {
342
- const src = Array.isArray(primary)
343
- ? primary
344
- : Array.isArray(fallback)
345
- ? fallback
346
- : null;
347
- if (!src) return null;
348
- const filtered = src.filter((s) => typeof s === 'string' && s.length > 0);
349
- return filtered.length > 0 ? filtered : null;
350
- }
351
-
352
- function extractStoryAcceptanceVerify(story) {
353
- // Stories carry inline
354
- // acceptance[] / verify[] arrays directly on the ticket. The
355
- // decomposer may emit these either at the top level of the ticket
356
- // (preferred) or nested under a structured `body` object (legacy
357
- // shape shared with the historical Task body). Read from both and
358
- // prefer the top-level fields when present.
359
- const fromBody =
360
- story.body && typeof story.body === 'object' && !Array.isArray(story.body)
361
- ? story.body
362
- : null;
363
- const out = {};
364
- const acceptance = pickStringArray(story.acceptance, fromBody?.acceptance);
365
- if (acceptance) out.acceptance = acceptance;
366
- const verify = pickStringArray(story.verify, fromBody?.verify);
367
- if (verify) out.verify = verify;
368
- return out;
369
- }
370
-
371
- function buildStoryOut({ story, layers, storySet }) {
372
- const deps = Array.isArray(story.depends_on) ? story.depends_on : [];
373
- const dependsOn = [
374
- ...new Set(deps.filter((d) => storySet.has(d) && d !== story.slug)),
375
- ];
376
-
377
- const out = {
378
- slug: story.slug,
379
- title: story.title,
380
- wave: layers.get(story.slug) ?? 0,
381
- };
382
- assignNonEmpty(out, 'body', renderBody(story.body));
383
- if (dependsOn.length > 0) out.dependsOn = dependsOn;
384
- assignNonEmpty(out, 'labels', sanitizeLabels(story.labels));
385
- const av = extractStoryAcceptanceVerify(story);
386
- if (av.acceptance) out.acceptance = av.acceptance;
387
- if (av.verify) out.verify = av.verify;
388
- return out;
389
- }
390
-
391
- function buildEpicOut(epic) {
392
- const out = { id: epic.id, title: epic.title };
393
- assignNonEmpty(out, 'body', renderBody(epic.body));
394
- assignNonEmpty(out, 'labels', sanitizeLabels(epic.labels));
395
- return out;
396
- }
397
-
398
- function buildGatesOut(gates) {
399
- if (!gates || typeof gates !== 'object') return null;
400
- const out = {};
401
- if (typeof gates.baseline === 'string' && gates.baseline.length > 0) {
402
- out.baseline = gates.baseline;
403
- }
404
- if (typeof gates.config === 'string' && gates.config.length > 0) {
405
- out.config = gates.config;
406
- }
407
- return Object.keys(out).length > 0 ? out : null;
408
- }
409
-
410
- function validateSpec(spec, schemaPath) {
411
- const effectiveSchemaPath = schemaPath ?? DEFAULT_SCHEMA_PATH;
412
- if (!existsSync(effectiveSchemaPath)) {
413
- throw new Error(
414
- `[spec-renderer] schema not found at ${effectiveSchemaPath}`,
415
- );
416
- }
417
- const validator = getValidator(effectiveSchemaPath);
418
- if (!validator(spec)) {
419
- throw new SpecRenderValidationError(
420
- normaliseAjvErrors(validator.errors ?? []),
421
- );
422
- }
423
- }
424
-
425
- export function renderSpec(tickets, opts = {}) {
426
- validateRenderSpecInputs(tickets, opts);
427
- const { epic, gates, schemaPath, validate = true } = opts;
428
-
429
- const { bySlug, storySlugs } = indexTickets(tickets);
430
- const { layers } = layerStories(storySlugs, bySlug);
431
- const storySet = new Set(storySlugs);
432
-
433
- const stories = storySlugs.map((storySlug) =>
434
- buildStoryOut({
435
- story: bySlug.get(storySlug),
436
- layers,
437
- storySet,
438
- }),
439
- );
440
-
441
- const spec = { epic: buildEpicOut(epic), stories };
442
- const gatesOut = buildGatesOut(gates);
443
- if (gatesOut) spec.gates = gatesOut;
444
-
445
- if (validate) validateSpec(spec, schemaPath);
446
- return spec;
447
- }