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,210 +0,0 @@
1
- /**
2
- * progress-reporter/signals.js — parsing and aggregation helpers for the
3
- * `story-run-progress` and `phase-timings` structured comments.
4
- *
5
- * Extracted from the parent `progress-reporter.js` so the aggregator
6
- * surface (phase percentile rollups, story-run-progress parsing) is
7
- * testable independently of the comment composition (`composition.js`)
8
- * and webhook transport (`transport.js`). Pure functions only — no
9
- * provider calls, no I/O — which makes this the natural home for the
10
- * shared state lookup tables (`PHASE_TO_STATE`, `PHASE_ORDER`,
11
- * `STATE_EMOJI`) and the structured-comment kind constants.
12
- */
13
-
14
- import { parseFencedJsonComment } from '../../structured-comment-parser.js';
15
-
16
- /**
17
- * Structured-comment kind for the rolled-up Epic-level progress
18
- * comment. Persisted via `composition.upsertEpicRunProgress` and read
19
- * back by tests + reconcilers.
20
- */
21
- export const EPIC_RUN_PROGRESS_TYPE = 'epic-run-progress';
22
-
23
- /**
24
- * Structured-comment kind for the per-Story phase-timings summary
25
- * posted by `story-close.js`. Read back by the ProgressReporter so the
26
- * Epic-level snapshot can aggregate median/p95 across waves.
27
- */
28
- export const PHASE_TIMINGS_TYPE = 'phase-timings';
29
-
30
- /**
31
- * Structured-comment kind for the per-Story run-progress snapshot that
32
- * `/deliver` upserts on every Task transition. Read by
33
- * ProgressReporter so the Epic-level table reflects sub-agent state in
34
- * near-real time instead of label-derived classifications.
35
- */
36
- export const STORY_RUN_PROGRESS_TYPE = 'story-run-progress';
37
-
38
- /**
39
- * Phase → high-level state classification. Lookup table flattens the
40
- * previous switch so cyclomatic complexity stays at 1 (one branch in the
41
- * `??` fallback) rather than 6 — keeps the CRAP score floor-bound under
42
- * coverage variance.
43
- */
44
- export const PHASE_TO_STATE = {
45
- done: 'done',
46
- blocked: 'blocked',
47
- implementing: 'in-flight',
48
- closing: 'in-flight',
49
- init: 'queued',
50
- };
51
-
52
- /**
53
- * Fixed ordering for the rendered phase-timings table. Matches the enum
54
- * in lib/util/phase-timer.js so rows line up with how operators think
55
- * about the story lifecycle rather than re-sorting by alphabet or
56
- * frequency.
57
- */
58
- export const PHASE_ORDER = [
59
- 'worktree-create',
60
- 'bootstrap',
61
- 'install',
62
- 'implement',
63
- 'lint',
64
- 'test',
65
- 'close',
66
- 'api-sync',
67
- ];
68
-
69
- /**
70
- * Emoji prefix per high-level state. Consumed by the rolled-up Epic table
71
- * (`composition.upsertEpicRunProgress`) so operators see a consistent icon
72
- * per state across the progress surface.
73
- */
74
- export const STATE_EMOJI = {
75
- done: '✅',
76
- blocked: '🚧',
77
- 'in-flight': '🔧',
78
- queued: '⏳',
79
- unknown: '❓',
80
- };
81
-
82
- /**
83
- * Map a `story-run-progress` phase to the high-level state label used
84
- * by the rendered tables. Returns `'unknown'` for any phase value that
85
- * isn't in the lookup table so an unexpected phase surfaces as an
86
- * unreadable row rather than a crash.
87
- */
88
- export function phaseToState(phase) {
89
- return PHASE_TO_STATE[phase] ?? 'unknown';
90
- }
91
-
92
- /**
93
- * Parse a `story-run-progress` structured comment posted by `/deliver`.
94
- * Returns `null` for any malformed body — the caller falls back to the
95
- * ticket-label state derivation in that case.
96
- *
97
- * Expected payload shape (JSON inside a fenced json codeblock):
98
- * {
99
- * storyId: number,
100
- * branch?: string,
101
- * phase: 'init'|'implementing'|'closing'|'blocked'|'done',
102
- * title?: string,
103
- * updatedAt?: string,
104
- * }
105
- */
106
- export function parseStoryRunProgressComment(comment) {
107
- const payload = parseFencedJsonComment(comment);
108
- if (!payload || typeof payload !== 'object') return null;
109
- const phase = typeof payload.phase === 'string' ? payload.phase : undefined;
110
- return {
111
- storyId: Number(payload.storyId),
112
- title: typeof payload.title === 'string' ? payload.title : '',
113
- phase,
114
- state: phaseToState(phase),
115
- };
116
- }
117
-
118
- /**
119
- * Extract the `{ phases, ... }` payload from a `phase-timings` structured
120
- * comment. Comment body is the fenced-JSON format produced by
121
- * `renderPhaseTimingsCommentBody` in story-close. Returns `null`
122
- * for any parse failure — the caller treats that as "no summary
123
- * available" without erroring out progress rendering.
124
- */
125
- export function parsePhaseTimingsComment(comment) {
126
- const payload = parseFencedJsonComment(comment);
127
- if (!payload || typeof payload !== 'object') return null;
128
- if (!Array.isArray(payload.phases)) return null;
129
- return {
130
- storyId: Number(payload.storyId),
131
- totalMs: Number(payload.totalMs) || 0,
132
- phases: payload.phases
133
- .filter(
134
- (p) =>
135
- p &&
136
- typeof p.name === 'string' &&
137
- Number.isFinite(Number(p.elapsedMs)),
138
- )
139
- .map((p) => ({ name: p.name, elapsedMs: Number(p.elapsedMs) })),
140
- };
141
- }
142
-
143
- /**
144
- * Aggregate a list of `phase-timings` summaries into per-phase median,
145
- * p95, and sample count. Returns phases ordered by the canonical
146
- * `PHASE_ORDER` so the rendered table always has the same row sequence —
147
- * operators should never have to hunt for the `install` row.
148
- */
149
- export function aggregatePhaseTimings(summaries) {
150
- const buckets = new Map();
151
- for (const s of summaries) {
152
- if (!s || !Array.isArray(s.phases)) continue;
153
- for (const p of s.phases) {
154
- if (!buckets.has(p.name)) buckets.set(p.name, []);
155
- buckets.get(p.name).push(p.elapsedMs);
156
- }
157
- }
158
- const rows = [];
159
- for (const name of PHASE_ORDER) {
160
- const samples = buckets.get(name);
161
- if (!samples || samples.length === 0) continue;
162
- rows.push({
163
- name,
164
- median: percentile(samples, 0.5),
165
- p95: percentile(samples, 0.95),
166
- n: samples.length,
167
- });
168
- }
169
- // Include any unexpected phase names at the tail so a future enum
170
- // addition surfaces in the table instead of being silently dropped.
171
- for (const [name, samples] of buckets.entries()) {
172
- if (PHASE_ORDER.includes(name)) continue;
173
- rows.push({
174
- name,
175
- median: percentile(samples, 0.5),
176
- p95: percentile(samples, 0.95),
177
- n: samples.length,
178
- });
179
- }
180
- return rows;
181
- }
182
-
183
- function percentile(samples, q) {
184
- const sorted = [...samples].sort((a, b) => a - b);
185
- if (sorted.length === 0) return 0;
186
- // Nearest-rank method — clamped so q=1 picks the last element.
187
- const idx = Math.min(
188
- sorted.length - 1,
189
- Math.max(0, Math.ceil(q * sorted.length) - 1),
190
- );
191
- return sorted[idx];
192
- }
193
-
194
- /**
195
- * Render the aggregated phase-timings table. Returns `null` when there
196
- * are no summaries to render so the caller can elide the section
197
- * entirely rather than emitting an empty stub.
198
- */
199
- export function renderPhaseTimingsSection(summaries) {
200
- if (!Array.isArray(summaries) || summaries.length === 0) return null;
201
- const rows = aggregatePhaseTimings(summaries);
202
- if (rows.length === 0) return null;
203
- const header = `### Phase timings (last ${summaries.length} completed stor${summaries.length === 1 ? 'y' : 'ies'})`;
204
- const table = [
205
- '| Phase | median ms | p95 ms | n |',
206
- '| --- | --- | --- | --- |',
207
- ...rows.map((r) => `| ${r.name} | ${r.median} | ${r.p95} | ${r.n} |`),
208
- ].join('\n');
209
- return `${header}\n\n${table}`;
210
- }
@@ -1,238 +0,0 @@
1
- /**
2
- * progress-reporter/transport.js — outbound I/O for the
3
- * `/deliver` progress narrative.
4
- *
5
- * Extracted from the parent `progress-reporter.js` so the
6
- * GitHub-comment posting surface (in `composition.js`) and the
7
- * progress-signal aggregation (in `signals.js`) can be reasoned about
8
- * independently of the webhook fan-out.
9
- *
10
- * Each `emit*` helper dispatches a curated event-shaped payload through
11
- * the caller-supplied `notify` function. The `notify` contract is owned
12
- * by `lib/notifications/*` and ultimately reaches the configured webhook
13
- * via gh-exec (the retry/backoff loop lives there, not here — this
14
- * module's role is the boundary). Failures from `notify` are swallowed
15
- * by design: a flaky webhook URL must never crash the runner mid-wave.
16
- *
17
- * The webhook events emitted from this module are:
18
- *
19
- * - `epic-started` — fired once at /deliver kickoff
20
- * - `epic-progress` — fired at wave boundaries / blocker transitions
21
- * - `epic-blocked` — wave aggregated to blocked/failed outside halt path
22
- * - `epic-unblocked` — operator flipped back to executing
23
- *
24
- * Each fire passes `skipComment: true` so the operator-facing GitHub
25
- * comments stay owned by `composition.js` (`upsertEpicRunProgress` and
26
- * `ProgressReporter.fire()`) — there is exactly one comment writer and
27
- * exactly one webhook writer per event.
28
- */
29
-
30
- /**
31
- * Webhook event name for the curated epic-progress rollup. Distinct from
32
- * the `epic-run-progress` structured-comment kind in `signals.js` — the
33
- * comment is the operator-facing per-poll snapshot on the Epic ticket,
34
- * the webhook event is the coarse-grained rollup that fires at wave
35
- * boundaries and after blocker transitions.
36
- */
37
- export const EPIC_PROGRESS_EVENT = 'epic-progress';
38
-
39
- /**
40
- * Fire a curated `epic-progress` webhook event. Event-driven only — called
41
- * per recorder beat and after blocker raise/clear transitions. Carries the
42
- * rollup payload `{ pct, done, total, phase, openBlockers }`, which Slack
43
- * consumers and downstream subscribers use to track epic progress without
44
- * subscribing to per-story chatter.
45
- *
46
- * The dispatch passes `skipComment: true` — the operator-facing GitHub
47
- * comment is owned by `ProgressReporter.fire()` and `upsertEpicRunProgress`,
48
- * not by this webhook fire.
49
- *
50
- * Failures are swallowed by design: the runner must keep moving even if
51
- * the webhook URL is misconfigured or the network is flaky.
52
- *
53
- * Story #4155 — the Epic `/deliver` runtime cut over to the continuous
54
- * ready-set scheduler, which has **no wave index**. The wave segment was
55
- * dropped from the message and the rollup payload entirely (rather than
56
- * rendered as `Wave undefined/undefined`); the sole live caller
57
- * (`wave-record-notifications.js`) never supplied wave coordinates.
58
- *
59
- * @param {{
60
- * notify: Function|null,
61
- * epicId: number,
62
- * done: number,
63
- * total: number,
64
- * phase?: string,
65
- * openBlockers?: Array<{ reason: string, storyId?: number }>,
66
- * logger?: { warn?: Function },
67
- * }} args
68
- * @returns {Promise<{ payload: object } | null>}
69
- */
70
- export async function emitEpicProgress({
71
- notify,
72
- epicId,
73
- done,
74
- total,
75
- phase,
76
- openBlockers = [],
77
- logger,
78
- }) {
79
- if (typeof notify !== 'function') return null;
80
- const epicIdNum = Number(epicId);
81
- if (!Number.isInteger(epicIdNum) || epicIdNum <= 0) return null;
82
- const totalN = Math.max(0, Number(total) || 0);
83
- const doneN = Math.max(0, Math.min(totalN, Number(done) || 0));
84
- const pct = totalN === 0 ? 0 : Math.round((doneN / totalN) * 100);
85
- const blockerCount = Array.isArray(openBlockers) ? openBlockers.length : 0;
86
- const blockerSuffix =
87
- blockerCount > 0
88
- ? ` · 🚧 ${blockerCount} blocker${blockerCount === 1 ? '' : 's'}`
89
- : '';
90
- const message = `Epic #${epicIdNum} progress · ${doneN}/${totalN} stories done (${pct}%)${blockerSuffix}`;
91
-
92
- const payload = {
93
- severity: blockerCount > 0 ? 'high' : 'medium',
94
- message,
95
- event: EPIC_PROGRESS_EVENT,
96
- level: 'epic',
97
- epicId: epicIdNum,
98
- };
99
- if (phase) payload.phase = phase;
100
-
101
- try {
102
- await notify(epicIdNum, payload, { skipComment: true });
103
- } catch (err) {
104
- logger?.warn?.(
105
- `[emitEpicProgress] notify dispatch failed (swallowed): ${err?.message ?? err}`,
106
- );
107
- return null;
108
- }
109
- return {
110
- payload: {
111
- pct,
112
- done: doneN,
113
- total: totalN,
114
- phase,
115
- openBlockers: openBlockers ?? [],
116
- },
117
- };
118
- }
119
-
120
- /**
121
- * Fire a curated `epic-started` webhook event at /deliver kickoff.
122
- * The Slack consumer anchors the rest of the epic narrative to this fire.
123
- * Failures are swallowed.
124
- *
125
- * Story #4155 — the ready-set runtime has no wave count, so the wave
126
- * segment was dropped from the message (rather than rendered as
127
- * `undefined wave(s)`); the sole live caller never supplied one.
128
- */
129
- export async function emitEpicStarted({
130
- notify,
131
- epicId,
132
- totalStories,
133
- title,
134
- logger,
135
- }) {
136
- if (typeof notify !== 'function') return null;
137
- const epicIdNum = Number(epicId);
138
- if (!Number.isInteger(epicIdNum) || epicIdNum <= 0) return null;
139
- const message = `Epic #${epicIdNum} started · ${totalStories} stor${totalStories === 1 ? 'y' : 'ies'}${title ? ` — ${title}` : ''}`;
140
- try {
141
- await notify(
142
- epicIdNum,
143
- {
144
- severity: 'medium',
145
- message,
146
- event: 'epic-started',
147
- level: 'epic',
148
- epicId: epicIdNum,
149
- },
150
- { skipComment: true },
151
- );
152
- } catch (err) {
153
- logger?.warn?.(
154
- `[emitEpicStarted] notify dispatch failed (swallowed): ${err?.message ?? err}`,
155
- );
156
- }
157
- return null;
158
- }
159
-
160
- /**
161
- * Fire a curated `epic-blocked` webhook event when a wave aggregates to
162
- * `blocked` or `failed` outside the `BlockerHandler.halt` code path (the
163
- * /deliver host-LLM loop has no handler instance — it calls this
164
- * helper directly from `epic-execute-record-wave.js`). The payload shape
165
- * matches the inline emit in `BlockerHandler.halt` so downstream consumers
166
- * see one canonical envelope regardless of which entry point fired.
167
- * Failures are swallowed.
168
- */
169
- export async function emitEpicBlocked({
170
- notify,
171
- epicId,
172
- reason,
173
- storyId,
174
- logger,
175
- }) {
176
- if (typeof notify !== 'function') return null;
177
- const epicIdNum = Number(epicId);
178
- if (!Number.isInteger(epicIdNum) || epicIdNum <= 0) return null;
179
- const storyPart = storyId ? ` (story #${storyId})` : '';
180
- const message = `🚨 Action Required: Epic #${epicIdNum}${storyPart} blocked: ${reason}`;
181
- try {
182
- await notify(
183
- epicIdNum,
184
- {
185
- severity: 'high',
186
- message,
187
- event: 'epic-blocked',
188
- level: 'epic',
189
- epicId: epicIdNum,
190
- },
191
- { skipComment: true },
192
- );
193
- } catch (err) {
194
- logger?.warn?.(
195
- `[emitEpicBlocked] notify dispatch failed (swallowed): ${err?.message ?? err}`,
196
- );
197
- }
198
- return null;
199
- }
200
-
201
- /**
202
- * Fire a curated `epic-unblocked` webhook event after the operator flips
203
- * the Epic label back to `agent::executing`. Paired with `epic-blocked` so
204
- * downstream consumers can track open-blocker lifecycle. Failures are
205
- * swallowed.
206
- */
207
- export async function emitEpicUnblocked({
208
- notify,
209
- epicId,
210
- resolvedBlocker,
211
- logger,
212
- }) {
213
- if (typeof notify !== 'function') return null;
214
- const epicIdNum = Number(epicId);
215
- if (!Number.isInteger(epicIdNum) || epicIdNum <= 0) return null;
216
- const reasonPart = resolvedBlocker?.reason
217
- ? ` (${resolvedBlocker.reason})`
218
- : '';
219
- const message = `Epic #${epicIdNum} unblocked${reasonPart} · resuming.`;
220
- try {
221
- await notify(
222
- epicIdNum,
223
- {
224
- severity: 'medium',
225
- message,
226
- event: 'epic-unblocked',
227
- level: 'epic',
228
- epicId: epicIdNum,
229
- },
230
- { skipComment: true },
231
- );
232
- } catch (err) {
233
- logger?.warn?.(
234
- `[emitEpicUnblocked] notify dispatch failed (swallowed): ${err?.message ?? err}`,
235
- );
236
- }
237
- return null;
238
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Shared bullet-formatting helpers for progress-signal detectors.
3
- *
4
- * Both crap-drift and maintainability-drift produce component-level
5
- * regression bullets and need the same two pure utilities — hoisted here
6
- * so they are maintained in one place (Story #3631, refs #3631).
7
- */
8
-
9
- /**
10
- * Comparator that sorts the wildcard component `'*'` before all named
11
- * components, with named components in locale order.
12
- *
13
- * @param {string} a
14
- * @param {string} b
15
- * @returns {number}
16
- */
17
- export function componentOrder(a, b) {
18
- if (a === '*') return -1;
19
- if (b === '*') return 1;
20
- return a.localeCompare(b);
21
- }
22
-
23
- /**
24
- * Formats a numeric gate value for display: integers render without a
25
- * decimal point; non-integers are fixed to two decimal places.
26
- *
27
- * @param {number} value
28
- * @returns {string}
29
- */
30
- export function formatNumber(value) {
31
- return Number.isInteger(value) ? String(value) : value.toFixed(2);
32
- }
@@ -1,203 +0,0 @@
1
- import nodeFs from 'node:fs';
2
- import path from 'node:path';
3
- import { resolveComponents } from '../../../baselines/components.js';
4
- import { componentOrder } from './_bullet-format.js';
5
-
6
- /**
7
- * Shared component-regression walk for the progress-signal drift detectors
8
- * (Story #3984). `crap-drift.js` and `maintainability-drift.js` previously
9
- * duplicated this baseline-rollup → per-component compare → bullet-list
10
- * shape verbatim; the only divergence was the breach comparator (CRAP is
11
- * "lower is better", maintainability is "higher is better") and the bullet
12
- * text. Both detectors now parameterize this walk.
13
- *
14
- * Pure — the caller loads the baseline via `lib/baselines/reader.js#load(...)`
15
- * and passes the resulting `{ rollup }` plus the gate config block.
16
- *
17
- * Only components whose rollup breaches the configured floor surface — a
18
- * breach in a component-scoped floor does NOT report against `*` unless
19
- * `*` itself breaches. This keeps the rollout narrowly targeted: when an
20
- * operator wires up a per-component floor for `api`, regressing `api`
21
- * names `api` — not `*`.
22
- *
23
- * @param {{
24
- * rollup?: Record<string, Record<string, number>>,
25
- * gateConfig?: { floors?: Record<string, Record<string, number>> } & object,
26
- * }} params
27
- * @param {{
28
- * isBreach: (value: number, floor: number) => boolean,
29
- * formatBullet: (name: string, axis: string, value: number, floor: number) => string,
30
- * }} spec
31
- * @returns {string[]}
32
- */
33
- export function walkComponentRegressions(params = {}, spec) {
34
- const rollup = params.rollup ?? {};
35
- const gateConfig = params.gateConfig ?? {};
36
- const floors = gateConfig.floors ?? {};
37
- const components = resolveComponents(gateConfig);
38
- const names = new Set([
39
- ...Object.keys(components),
40
- ...Object.keys(floors),
41
- ...Object.keys(rollup),
42
- ]);
43
- const bullets = [];
44
- for (const name of [...names].sort(componentOrder)) {
45
- const aggregate = rollup[name];
46
- if (!aggregate || typeof aggregate !== 'object') continue;
47
- const floor = floors[name] ?? floors['*'];
48
- if (!floor || typeof floor !== 'object') continue;
49
- for (const axis of Object.keys(floor).sort()) {
50
- const target = floor[axis];
51
- const value = aggregate[axis];
52
- if (typeof target !== 'number' || !Number.isFinite(target)) continue;
53
- if (typeof value !== 'number' || !Number.isFinite(value)) continue;
54
- if (!spec.isBreach(value, target)) continue;
55
- bullets.push(spec.formatBullet(name, axis, value, target));
56
- }
57
- }
58
- return bullets;
59
- }
60
-
61
- /**
62
- * Shared wave-start snapshot persistence for the drift detectors. Both
63
- * detectors persist a `{ capturedAt, ...metadata, scores }` JSON document
64
- * under `<cwd>/<baselineDir>/<filename>` so a resumed epic run can re-read
65
- * the wave-start anchor rather than lose it, and both treat persistence as
66
- * best-effort (the in-memory baseline still works when a write fails).
67
- *
68
- * @param {{
69
- * fs: { readFileSync?: Function, writeFileSync?: Function, mkdirSync?: Function },
70
- * baselinePath: string,
71
- * metadata?: Record<string, unknown>,
72
- * }} opts
73
- */
74
- function createSnapshotStore({ fs, baselinePath, metadata = {} }) {
75
- return {
76
- persist(scores) {
77
- if (!fs.writeFileSync) return;
78
- try {
79
- fs.mkdirSync?.(path.dirname(baselinePath), { recursive: true });
80
- fs.writeFileSync(
81
- baselinePath,
82
- JSON.stringify(
83
- { capturedAt: new Date().toISOString(), ...metadata, scores },
84
- null,
85
- 2,
86
- ),
87
- );
88
- } catch {
89
- // persistence is best-effort; the in-memory baseline still works
90
- }
91
- },
92
-
93
- load() {
94
- if (!fs.readFileSync) return null;
95
- try {
96
- const raw = fs.readFileSync(baselinePath, 'utf-8');
97
- const parsed = JSON.parse(raw);
98
- return parsed?.scores ?? null;
99
- } catch {
100
- return null;
101
- }
102
- },
103
- };
104
- }
105
-
106
- /**
107
- * Shared per-file/per-method drift-detector skeleton for the progress-signal
108
- * detectors (Story #4076). `crap-drift.js` and `maintainability-drift.js`
109
- * previously duplicated the same `{ baselinePath, captureBaseline,
110
- * loadBaseline, detect }` shape — identical snapshot-store wiring, identical
111
- * "distinct from canonical baseline" framing, and identical
112
- * swallow-and-warn resilience. The only divergence is the per-axis scoring
113
- * (`scoreFile`), the snapshot value extracted from a score (`captureScore`),
114
- * and the per-detect comparison that emits bullets (`detect`). Both detectors
115
- * now supply those deltas to this factory, mirroring the "shared walker +
116
- * per-axis delta" pattern already established by `walkComponentRegressions`.
117
- *
118
- * The factory owns:
119
- *
120
- * - `fs` / `cwd` / `files` resolution from `opts`.
121
- * - The `<cwd>/<baselineDir>/<baselineFilename>` baseline path and the
122
- * `createSnapshotStore` wiring (with caller-supplied `metadata`).
123
- * - The in-memory `baseline` cache and the `captureBaseline` /
124
- * `loadBaseline` lifecycle.
125
- *
126
- * The caller owns:
127
- *
128
- * - `scoreFile(relPath, ctx)` — returns the per-file score (any shape) or
129
- * `null` when the file can't be scored. `ctx` is whatever
130
- * `beforeScore()` returned for this pass (e.g. a coverage map), or
131
- * `undefined` when `beforeScore` is omitted.
132
- * - `captureScore(score)` — maps a `scoreFile` result to the value
133
- * persisted in the snapshot (e.g. extract `crap` from each method row).
134
- * - `detect({ baseline, scoreFile })` — async; returns the bullet list.
135
- * Receives the loaded baseline and a `scoreFile(relPath)` bound to this
136
- * pass's score context so the per-axis compare stays free of plumbing.
137
- * - `beforeScore()` (optional) — runs once per `captureBaseline` / `detect`
138
- * pass and returns the score context threaded into `scoreFile`.
139
- *
140
- * @param {{
141
- * cwd?: string,
142
- * files?: string[],
143
- * fs?: { readFileSync?: Function, writeFileSync?: Function, mkdirSync?: Function, existsSync?: Function },
144
- * baselineDir?: string,
145
- * baselineFilename: string,
146
- * metadata?: Record<string, unknown>,
147
- * beforeScore?: () => unknown,
148
- * scoreFile: (relPath: string, ctx: unknown) => unknown,
149
- * captureScore: (score: unknown) => unknown,
150
- * detect: (args: { baseline: Record<string, unknown>, scoreFile: (relPath: string) => unknown }) => Promise<string[]>,
151
- * }} opts
152
- */
153
- export function createDriftDetector(opts = {}) {
154
- const fs = opts.fs ?? nodeFs;
155
- const cwd = opts.cwd ?? process.cwd();
156
- const files = Array.isArray(opts.files) ? [...opts.files] : [];
157
- const baselineDir = opts.baselineDir ?? '.agents/state';
158
- const baselinePath = path.join(cwd, baselineDir, opts.baselineFilename);
159
- const beforeScore = opts.beforeScore ?? (() => undefined);
160
- const scoreFile = opts.scoreFile;
161
- const captureScore = opts.captureScore;
162
- const runDetect = opts.detect;
163
- const store = createSnapshotStore({
164
- fs,
165
- baselinePath,
166
- metadata: opts.metadata ?? {},
167
- });
168
-
169
- let baseline = null;
170
-
171
- return {
172
- get baselinePath() {
173
- return baselinePath;
174
- },
175
-
176
- captureBaseline() {
177
- const ctx = beforeScore();
178
- const snapshot = {};
179
- for (const f of files) {
180
- const score = scoreFile(f, ctx);
181
- if (score == null) continue;
182
- snapshot[f] = captureScore(score);
183
- }
184
- baseline = snapshot;
185
- store.persist(snapshot);
186
- return snapshot;
187
- },
188
-
189
- loadBaseline() {
190
- baseline = store.load();
191
- return baseline;
192
- },
193
-
194
- async detect() {
195
- if (!baseline) return [];
196
- const ctx = beforeScore();
197
- return runDetect({
198
- baseline,
199
- scoreFile: (relPath) => scoreFile(relPath, ctx),
200
- });
201
- },
202
- };
203
- }