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,571 +0,0 @@
1
- /**
2
- * phases/compose-body.js — retro Phase 2: compose the retro markdown body.
3
- *
4
- * Pure: given an aggregated counts/signals input, produce the retro
5
- * markdown body plus the compact/scorecard envelope. Selects the compact
6
- * (clean-manifest) or full retro shape via `isCleanManifest`.
7
- *
8
- * `normalizeInterventionCount` is exported so the post-and-mirror phase
9
- * can reuse the same clamping logic when forwarding the runtime's
10
- * `manualInterventions` count into the body composer.
11
- */
12
-
13
- import { isCleanManifest } from '../../retro-heuristics.js';
14
- import { classifyPerfSignals } from '../../retro-perf-heuristics.js';
15
-
16
- /**
17
- * Pure: clamp a candidate count to a non-negative integer. Used to
18
- * normalize the `manualInterventions` count plumbed in from the
19
- * epic-run-state-store snapshot before it lands in the scorecard.
20
- * Non-finite, negative, or non-numeric values collapse to 0.
21
- */
22
- export function normalizeInterventionCount(value) {
23
- if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
24
- return 0;
25
- }
26
- return Math.trunc(value);
27
- }
28
-
29
- /**
30
- * Pure: does `routedProposals` carry at least one actionable item (a
31
- * framework- or consumer-routed `gh issue create` proposal)? Story #4417 —
32
- * the compact retro shape (and therefore the `automerge-verdict`
33
- * `cleanSprint: true` flag it drives) MUST be suppressed whenever an
34
- * actionable proposal exists, regardless of `forceFull` or the
35
- * comment-derived counts: the clean-sprint verdict is an auto-merge input
36
- * and must never read "clean" while actionable friction sits in the routed
37
- * proposals. Discarded (single-occurrence) items do NOT count — they are
38
- * the retro's explicit "nothing to file" bucket.
39
- *
40
- * @param {{ framework?: object[], consumer?: object[] } | null | undefined} routedProposals
41
- * @returns {boolean}
42
- */
43
- export function hasActionableProposals(routedProposals) {
44
- if (
45
- !routedProposals ||
46
- typeof routedProposals !== 'object' ||
47
- Array.isArray(routedProposals)
48
- ) {
49
- return false;
50
- }
51
- const framework = Array.isArray(routedProposals.framework)
52
- ? routedProposals.framework
53
- : [];
54
- const consumer = Array.isArray(routedProposals.consumer)
55
- ? routedProposals.consumer
56
- : [];
57
- return framework.length > 0 || consumer.length > 0;
58
- }
59
-
60
- /**
61
- * Pure: derive the recurring-defect-class signal from the routed-proposal
62
- * sections (Story #4135 / Epic #4131, F11).
63
- *
64
- * The routed-proposals composer (`retro-proposals.js`) already split the
65
- * Epic's source-tagged friction into `framework` / `consumer` actionable
66
- * items — a category lands there only when it recurred ≥2 times across the
67
- * Epic OR was force-flagged by an unresolved `agent::blocked` event. Those
68
- * are exactly the **recurring classes** of review/deliver-caught issues F11
69
- * tracks, so we lift them verbatim rather than re-deriving a parallel
70
- * threshold. Each entry carries the `friction::<category>` label the
71
- * composer stamps onto its `gh issue create` command — that label is the
72
- * join key the `/plan` Phase 0 prior-feedback fetcher reads back to surface
73
- * recurring classes to the planner.
74
- *
75
- * Determinism: the two actionable arrays are already sorted by `category`
76
- * ASC by the composer; we concatenate framework-then-consumer and re-sort by
77
- * `category` so the merged signal is stable regardless of which source
78
- * contributed a class.
79
- *
80
- * No-op-safe: a null / non-object / shapeless `routedProposals` (or one with
81
- * empty actionable arrays) yields `[]` — the common clean-sprint case.
82
- *
83
- * @param {{ framework?: object[], consumer?: object[] } | null | undefined} routedProposals
84
- * @returns {Array<{ category: string, occurrences: number, source: 'framework'|'consumer', label: string }>}
85
- */
86
- export function deriveDefectClasses(routedProposals) {
87
- if (
88
- !routedProposals ||
89
- typeof routedProposals !== 'object' ||
90
- Array.isArray(routedProposals)
91
- ) {
92
- return [];
93
- }
94
- const framework = Array.isArray(routedProposals.framework)
95
- ? routedProposals.framework
96
- : [];
97
- const consumer = Array.isArray(routedProposals.consumer)
98
- ? routedProposals.consumer
99
- : [];
100
-
101
- const out = [];
102
- for (const item of [...framework, ...consumer]) {
103
- if (!item || typeof item !== 'object') continue;
104
- const category =
105
- typeof item.category === 'string' ? item.category.trim() : '';
106
- if (category.length === 0) continue;
107
- const occurrences =
108
- typeof item.occurrences === 'number' && Number.isFinite(item.occurrences)
109
- ? item.occurrences
110
- : 0;
111
- const source = item.source === 'framework' ? 'framework' : 'consumer';
112
- out.push({
113
- category,
114
- occurrences,
115
- source,
116
- label: `friction::${category}`,
117
- });
118
- }
119
- out.sort((a, b) => a.category.localeCompare(b.category));
120
- return out;
121
- }
122
-
123
- /**
124
- * Pure: compose the retro markdown body. Exported for tests so they can
125
- * verify the body shape without round-tripping through a stub provider.
126
- *
127
- * Story #2289 adds `counts.interventions` — sourced from the
128
- * `manualInterventions` array on the `epic-run-state` snapshot (the
129
- * same list that disqualifies an Epic from auto-merge). Non-zero
130
- * interventions route to the full retro shape via `isCleanManifest`.
131
- *
132
- * @param {{
133
- * epicId: number,
134
- * epicTitle?: string,
135
- * counts: { friction: number, parked: number, recuts: number, hitl: number, interventions?: number },
136
- * storyPerfSummaries?: object[],
137
- * epicPerfReport?: object|null,
138
- * parkedFollowOns?: { recuts: object[], parked: object[] },
139
- * timestamp?: string,
140
- * forceFull?: boolean,
141
- * }} input
142
- * @returns {{ body: string, compact: boolean, scorecard: object }}
143
- */
144
- export function composeRetroBody(input) {
145
- const {
146
- epicId,
147
- epicTitle = `Epic ${epicId}`,
148
- counts,
149
- storyPerfSummaries = [],
150
- epicPerfReport = null,
151
- parkedFollowOns = { recuts: [], parked: [] },
152
- routedProposals = null,
153
- timestamp = new Date().toISOString(),
154
- forceFull = false,
155
- perfThresholds = null,
156
- } = input;
157
-
158
- const interventions = normalizeInterventionCount(counts?.interventions);
159
- // Story #4417 — the compact shape requires BOTH a clean manifest AND zero
160
- // actionable routed proposals. The routed proposals and the counts are
161
- // derived from the same unified signals scan (gather-signals.js), so this
162
- // guard closes the window where the comment-derived counts read "clean"
163
- // while the ndjson-derived routed proposals hold an actionable item.
164
- const compact =
165
- !forceFull &&
166
- isCleanManifest({ ...counts, interventions }) &&
167
- !hasActionableProposals(routedProposals);
168
- const heading = `## 🪞 Sprint Retrospective — Epic #${epicId}: ${epicTitle}`;
169
- const generatedLine = `_Generated ${timestamp}_`;
170
- const scorecardRows = [
171
- `| agent::blocked Events Raised | ${counts.hitl} |`,
172
- `| Manual Interventions | ${interventions} |`,
173
- `| Friction Events | ${counts.friction} |`,
174
- ];
175
- const scorecard = {
176
- hitl: counts.hitl,
177
- friction: counts.friction,
178
- parked: counts.parked,
179
- recuts: counts.recuts,
180
- interventions,
181
- };
182
- const completeMarker = `<!-- retro-complete: ${timestamp} -->`;
183
- // Machine-readable auto-merge verdict trailer (Story #3901). The
184
- // Phase 8.5 `AutomergePredicate` reads `cleanSprint` from THIS trailer
185
- // — a parsed JSON boolean — rather than string-matching the human-facing
186
- // "🟢 Clean sprint" prose, which was a brittle emoji `.includes()` that
187
- // false-positived on any retro body that happened to quote the marker
188
- // and false-negatived on any compact-body copy edit. `cleanSprint`
189
- // tracks the compact shape exactly (a full/forced retro is never a
190
- // clean sprint); the scorecard is mirrored so the predicate can surface
191
- // the disqualifying counts without re-parsing the markdown table.
192
- const automergeTrailer = `<!-- automerge-verdict: ${JSON.stringify({
193
- cleanSprint: compact,
194
- scorecard,
195
- })} -->`;
196
-
197
- if (compact) {
198
- const body = [
199
- heading,
200
- '',
201
- generatedLine,
202
- '',
203
- '🟢 Clean sprint — zero friction, zero parked follow-ons, zero recuts, zero agent::blocked events, zero manual interventions.',
204
- '',
205
- '### Sprint Scorecard',
206
- '',
207
- '| Metric | Value |',
208
- '| ---------------------------- | ----- |',
209
- ...scorecardRows,
210
- '',
211
- '### Session Observations',
212
- '',
213
- '_Nothing notable beyond the scorecard._',
214
- '',
215
- '### Action Items for Next Epic',
216
- '',
217
- '_None._',
218
- '',
219
- completeMarker,
220
- automergeTrailer,
221
- ].join('\n');
222
- return { body, compact: true, scorecard };
223
- }
224
-
225
- // Full path — six sections.
226
- const hotspotLines =
227
- epicPerfReport &&
228
- Array.isArray(epicPerfReport.topHotspots) &&
229
- epicPerfReport.topHotspots.length > 0
230
- ? epicPerfReport.topHotspots.map(
231
- (h) =>
232
- `- \`${h.phase}\` — ${h.occurrences} occurrence(s), avg ratio ${
233
- typeof h.avgRatio === 'number' ? h.avgRatio.toFixed(2) : 'n/a'
234
- }`,
235
- )
236
- : ['_No epic-perf-report available._'];
237
-
238
- const parkedLines =
239
- parkedFollowOns.parked.length > 0
240
- ? parkedFollowOns.parked.map(
241
- (p) =>
242
- `- Adopt or close parked follow-on #${p.storyId ?? p.id ?? '?'}`,
243
- )
244
- : [];
245
- const recutLines =
246
- parkedFollowOns.recuts.length > 0
247
- ? parkedFollowOns.recuts.map(
248
- (r) => `- Recut #${r.storyId ?? r.id ?? '?'} attributed to manifest`,
249
- )
250
- : [];
251
- const legacyActionItems = [...parkedLines, ...recutLines];
252
- const legacyActionItemsBody =
253
- legacyActionItems.length > 0 ? legacyActionItems.join('\n') : '_None._';
254
-
255
- // Story #2558 — routed-proposals mode. When routedProposals is supplied
256
- // AND any of the three buckets is non-empty, render the three explicit
257
- // sections in deterministic order ABOVE the retro-complete marker:
258
- // 1. Proposed issues — consumer repo
259
- // 2. Proposed issues — framework repo
260
- // 3. One-off / discarded
261
- // Otherwise the legacy "Action Items for Next Epic" section renders.
262
- const routedSectionsBlock = renderRoutedSections(routedProposals);
263
-
264
- const actionSection =
265
- routedSectionsBlock === null
266
- ? ['### Action Items for Next Epic', '', legacyActionItemsBody]
267
- : routedSectionsBlock;
268
-
269
- // Story #3042 — Performance Signals + Recommended Follow-Ons. Both
270
- // sections are emitted only when (1) the persisted epic-perf-report is
271
- // present AND (2) `classifyPerfSignals` returns at least one signal.
272
- // Otherwise the entire pair is suppressed so the retro stays compact.
273
- const perfReportForHeuristics = epicPerfReport
274
- ? { ...epicPerfReport, storyPerfSummaries }
275
- : null;
276
- const perfSignals = perfReportForHeuristics
277
- ? classifyPerfSignals(perfReportForHeuristics, perfThresholds)
278
- : [];
279
- const perfSignalsSection = renderPerfSignalsSection(perfSignals);
280
- const followOnsSection = renderFollowOnsSection(perfSignals);
281
-
282
- const body = [
283
- heading,
284
- '',
285
- generatedLine,
286
- '',
287
- '### Sprint Scorecard',
288
- '',
289
- '| Metric | Value |',
290
- '| ---------------------------- | ----- |',
291
- ...scorecardRows,
292
- '',
293
- '### What Went Well',
294
- '',
295
- '_(populate from execution telemetry — extracted retro module emits a placeholder; deeper analysis is the operator follow-up.)_',
296
- '',
297
- '### What Could Be Improved',
298
- '',
299
- '#### Top hotspots',
300
- '',
301
- ...hotspotLines,
302
- '',
303
- '### Architectural Debt',
304
- '',
305
- '_(no automated detection in v5.40.0 — operator review required.)_',
306
- '',
307
- '### Protocol Optimization Recommendations (Self-Healing)',
308
- '',
309
- '_(operator follow-up.)_',
310
- '',
311
- ...actionSection,
312
- '',
313
- ...perfSignalsSection,
314
- ...followOnsSection,
315
- completeMarker,
316
- automergeTrailer,
317
- ].join('\n');
318
- return { body, compact: false, scorecard };
319
- }
320
-
321
- /**
322
- * Pure: render the `## Performance Signals` section. Returns `[]` (so the
323
- * caller can spread it conditionally) when no signal trips. The renderer
324
- * emits one bullet per signal, naming the kind, the offending wave(s),
325
- * the observed value, and the threshold that produced the signal.
326
- *
327
- * @param {Array<object>} signals
328
- * @returns {string[]}
329
- */
330
- function renderPerfSignalsSection(signals) {
331
- if (!Array.isArray(signals) || signals.length === 0) return [];
332
- const lines = ['## Performance Signals', ''];
333
- for (const s of signals) {
334
- lines.push(`- ${describeSignal(s)}`);
335
- }
336
- lines.push('');
337
- return lines;
338
- }
339
-
340
- /**
341
- * Pure: render the `## Recommended Follow-Ons` section. One stanza per
342
- * signal, each carrying a Conventional-Commits-shaped title and a body
343
- * including the suggested `meta::framework-gap` label.
344
- *
345
- * Each stanza is a `gh issue create` command operators can paste directly:
346
- * the title is in Conventional-Commits form, and the body names the
347
- * trigger metric so the planner has the context for triage.
348
- *
349
- * @param {Array<object>} signals
350
- * @returns {string[]}
351
- */
352
- function renderFollowOnsSection(signals) {
353
- if (!Array.isArray(signals) || signals.length === 0) return [];
354
- const lines = ['## Recommended Follow-Ons', ''];
355
- for (const s of signals) {
356
- const title = followOnTitle(s);
357
- const body = followOnBody(s);
358
- lines.push(`- **${title}**`);
359
- lines.push('');
360
- lines.push('```sh');
361
- lines.push(
362
- `gh issue create --title ${shellEscape(title)} --label meta::framework-gap --body ${shellEscape(body)}`,
363
- );
364
- lines.push('```');
365
- lines.push('');
366
- }
367
- return lines;
368
- }
369
-
370
- /**
371
- * Human-readable one-liner for a perf signal — used as the bullet text
372
- * under `## Performance Signals`. Pure; signal kinds it doesn't know
373
- * collapse to a generic shape so the renderer never produces empty
374
- * strings for forward-compatible signal kinds.
375
- *
376
- * @param {object} s
377
- * @returns {string}
378
- */
379
- function describeSignal(s) {
380
- if (!s || typeof s !== 'object') return 'unknown perf signal';
381
- if (s.kind === 'low-utilisation') {
382
- const pct = formatPercent(s.utilisation);
383
- const thr = formatPercent(s.threshold);
384
- return `low-utilisation: wave ${s.waveIndex} ran at ${pct} (threshold ${thr})`;
385
- }
386
- if (s.kind === 'high-bootstrap-share') {
387
- const pct = formatPercent(s.share);
388
- const thr = formatPercent(s.threshold);
389
- return `high-bootstrap-share: story-init consumed ${pct} of Story execution time (threshold ${thr})`;
390
- }
391
- if (s.kind === 'cap-binding-run') {
392
- return `cap-binding-run: waves ${s.fromWaveIndex}–${s.toWaveIndex} (${s.runLength} consecutive waves) saturated the concurrency cap`;
393
- }
394
- return `${s.kind ?? 'unknown'} perf signal`;
395
- }
396
-
397
- /**
398
- * Conventional-Commits-shaped title for a perf signal's follow-on. Pure.
399
- *
400
- * @param {object} s
401
- * @returns {string}
402
- */
403
- function followOnTitle(s) {
404
- if (!s || typeof s !== 'object')
405
- return 'perf: investigate unknown perf signal';
406
- if (s.kind === 'low-utilisation') {
407
- return `perf(epic-deliver): investigate low utilisation in wave ${s.waveIndex}`;
408
- }
409
- if (s.kind === 'high-bootstrap-share') {
410
- return 'perf(story-init): reduce bootstrap share of Story execution time';
411
- }
412
- if (s.kind === 'cap-binding-run') {
413
- return `perf(deliver-runner): raise concurrency cap to break ${s.runLength}-wave cap-binding run`;
414
- }
415
- return `perf: investigate ${s.kind} signal`;
416
- }
417
-
418
- /**
419
- * Body for the paste-ready follow-on stanza. Includes the trigger metric
420
- * so the planner has the context for triage.
421
- *
422
- * @param {object} s
423
- * @returns {string}
424
- */
425
- function followOnBody(s) {
426
- const trigger = describeSignal(s);
427
- return [
428
- `Auto-suggested by retro-perf-heuristics (Story #3042).`,
429
- ``,
430
- `Trigger: ${trigger}.`,
431
- ``,
432
- `Apply the meta::framework-gap label so /plan Phase 0 surfaces it on the next planning pass.`,
433
- ].join('\n');
434
- }
435
-
436
- function formatPercent(n) {
437
- if (typeof n !== 'number' || !Number.isFinite(n)) return 'n/a';
438
- return `${(n * 100).toFixed(1)}%`;
439
- }
440
-
441
- /**
442
- * Minimal POSIX shell-quote for the `gh issue create` paste-ready
443
- * command. We single-quote and escape embedded single quotes so the
444
- * stanza works under bash/zsh/PowerShell-Core. The retro body is
445
- * read-only documentation, so the quoting is a UX convenience, not a
446
- * security boundary — but the helper is total nonetheless.
447
- *
448
- * @param {string} s
449
- * @returns {string}
450
- */
451
- function shellEscape(s) {
452
- const str = String(s ?? '');
453
- return `'${str.replace(/'/g, `'\\''`)}'`;
454
- }
455
-
456
- /**
457
- * Render the body lines (everything below a section heading and its trailing
458
- * blank) for a "proposed issues" bucket — the consumer and framework sections
459
- * share this shape. Empty buckets collapse to a single `_None._`; populated
460
- * buckets emit, per item, either the **filed issue reference** (when the
461
- * retro auto-filer already filed it — Story #4418, stamped as
462
- * `item.filedIssue`) or the paste-ready fenced `gh issue create` stanza (the
463
- * toggle-OFF / filing-skipped fallback).
464
- *
465
- * @param {object[]} items
466
- * @returns {string[]}
467
- */
468
- function renderIssueBucket(items) {
469
- if (items.length === 0) return ['_None._'];
470
- const lines = [];
471
- for (const item of items) {
472
- lines.push(`- **${item.title ?? item.category}**`);
473
- lines.push('');
474
- if (item.filedIssue && item.filedIssue.url) {
475
- const ref = Number.isInteger(item.filedIssue.number)
476
- ? `#${item.filedIssue.number}`
477
- : 'issue';
478
- lines.push(` Filed: [${ref}](${item.filedIssue.url})`);
479
- } else {
480
- lines.push('```sh');
481
- lines.push(String(item.command ?? ''));
482
- lines.push('```');
483
- }
484
- lines.push('');
485
- }
486
- return lines;
487
- }
488
-
489
- /**
490
- * Render the body lines for the "one-off / discarded" bucket — one bullet per
491
- * discarded class naming its occurrence count and source, or `_None._`.
492
- *
493
- * @param {object[]} items
494
- * @returns {string[]}
495
- */
496
- function renderDiscardedBucket(items) {
497
- if (items.length === 0) return ['_None._'];
498
- return items.map(
499
- (d) =>
500
- `- \`${d.category}\` (${d.occurrences ?? 1} occurrence, source: ${d.source ?? 'consumer'})`,
501
- );
502
- }
503
-
504
- /**
505
- * Descriptor table for the three routed-proposal sections, in deterministic
506
- * emit order (consumer → framework → discarded). Each descriptor pairs a
507
- * heading, the `routedProposals` field it reads, and a body renderer.
508
- * {@link renderRoutedSections} walks the table once, so reordering or adding a
509
- * section is a data edit here rather than another copy-pasted emit block.
510
- *
511
- * The former "Proposed memory updates" section was deleted in the Epic
512
- * #4406 signal-contract cutover — no writer ever produced the memory-pane
513
- * records it rendered.
514
- *
515
- * @type {Array<{ heading: string, field: string, renderBucket: (items: object[]) => string[] }>}
516
- */
517
- const ROUTED_SECTIONS = [
518
- {
519
- heading: '### Proposed issues — consumer repo',
520
- field: 'consumer',
521
- renderBucket: renderIssueBucket,
522
- },
523
- {
524
- heading: '### Proposed issues — framework repo',
525
- field: 'framework',
526
- renderBucket: renderIssueBucket,
527
- },
528
- {
529
- heading: '### One-off / discarded',
530
- field: 'discarded',
531
- renderBucket: renderDiscardedBucket,
532
- },
533
- ];
534
-
535
- /**
536
- * Pure: render the four routed-proposal sections in deterministic order.
537
- * Returns `null` when `routedProposals` is absent or fully empty — the
538
- * caller falls back to the legacy "Action Items for Next Epic" section so
539
- * back-compat callers see no shape change.
540
- *
541
- * @param {{ framework: object[], consumer: object[], memory: object[], discarded: object[] } | null} routedProposals
542
- * @returns {string[] | null}
543
- */
544
- function renderRoutedSections(routedProposals) {
545
- if (
546
- !routedProposals ||
547
- typeof routedProposals !== 'object' ||
548
- Array.isArray(routedProposals)
549
- ) {
550
- return null;
551
- }
552
- const buckets = ROUTED_SECTIONS.map((section) => {
553
- const items = Array.isArray(routedProposals[section.field])
554
- ? routedProposals[section.field]
555
- : [];
556
- return { section, items };
557
- });
558
- if (buckets.every(({ items }) => items.length === 0)) {
559
- return null;
560
- }
561
-
562
- // Each section renders as `[heading, '', ...body]`; a single blank-line
563
- // separator sits between consecutive sections (no trailing separator after
564
- // the last), reproducing the original hand-unrolled push sequence exactly.
565
- const out = [];
566
- for (const { section, items } of buckets) {
567
- if (out.length > 0) out.push('');
568
- out.push(section.heading, '', ...section.renderBucket(items));
569
- }
570
- return out;
571
- }