mandrel 1.94.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (560) hide show
  1. package/.agents/README.md +116 -99
  2. package/.agents/agents/acceptance-critic.md +9 -7
  3. package/.agents/agents/story-worker.md +45 -51
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +498 -1287
  6. package/.agents/docs/agentrc-reference.json +185 -80
  7. package/.agents/docs/configuration.md +132 -190
  8. package/.agents/docs/execution-reference.md +51 -25
  9. package/.agents/docs/quality-gates.md +25 -33
  10. package/.agents/docs/workflows.md +8 -8
  11. package/.agents/instructions.md +113 -139
  12. package/.agents/rules/ci-remediation.md +11 -15
  13. package/.agents/rules/git-conventions-reference.md +48 -58
  14. package/.agents/rules/git-conventions.md +16 -22
  15. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  16. package/.agents/schemas/agentrc.schema.json +83 -254
  17. package/.agents/schemas/audit-rules.json +59 -1
  18. package/.agents/schemas/audit-rules.schema.json +33 -1
  19. package/.agents/schemas/lifecycle/README.md +1 -2
  20. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  21. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  22. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  23. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  24. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  25. package/.agents/schemas/signal-event.schema.json +3 -3
  26. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  27. package/.agents/schemas/validation-evidence.schema.json +1 -1
  28. package/.agents/scripts/acceptance-eval.js +22 -66
  29. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  30. package/.agents/scripts/audit-to-stories.js +7 -7
  31. package/.agents/scripts/boot-sweep.js +1 -1
  32. package/.agents/scripts/bootstrap.js +3 -3
  33. package/.agents/scripts/check-dead-exports.js +43 -104
  34. package/.agents/scripts/check-doc-links.js +2 -2
  35. package/.agents/scripts/check-lifecycle-lint.js +7 -10
  36. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  37. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  38. package/.agents/scripts/deliver-recover.js +122 -0
  39. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  40. package/.agents/scripts/evidence-gate.js +20 -50
  41. package/.agents/scripts/generate-skills-index.js +17 -1
  42. package/.agents/scripts/generate-workflows-doc.js +4 -4
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  44. package/.agents/scripts/lib/Logger.js +6 -10
  45. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  46. package/.agents/scripts/lib/audit-suite/selector.js +328 -28
  47. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  48. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  49. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -15
  50. package/.agents/scripts/lib/baselines/reader.js +1 -6
  51. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  52. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  53. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  54. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  55. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  56. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  57. package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
  58. package/.agents/scripts/lib/checks/index.js +3 -2
  59. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  60. package/.agents/scripts/lib/checks/state.js +17 -248
  61. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
  62. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  63. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  64. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  65. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  66. package/.agents/scripts/lib/cli-args.js +39 -9
  67. package/.agents/scripts/lib/close-validation/gates.js +15 -15
  68. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  69. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  70. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  71. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  72. package/.agents/scripts/lib/config/ci.js +6 -31
  73. package/.agents/scripts/lib/config/delivery-routing.js +52 -35
  74. package/.agents/scripts/lib/config/explain.js +61 -48
  75. package/.agents/scripts/lib/config/github.js +7 -5
  76. package/.agents/scripts/lib/config/limits.js +29 -80
  77. package/.agents/scripts/lib/config/paths.js +0 -2
  78. package/.agents/scripts/lib/config/quality.js +12 -15
  79. package/.agents/scripts/lib/config/runners.js +20 -66
  80. package/.agents/scripts/lib/config/temp-paths.js +30 -63
  81. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  82. package/.agents/scripts/lib/config-resolver.js +2 -7
  83. package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
  84. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
  85. package/.agents/scripts/lib/config-settings-schema.js +100 -60
  86. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  87. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  88. package/.agents/scripts/lib/dependency-parser.js +3 -2
  89. package/.agents/scripts/lib/doc-tiers.js +2 -2
  90. package/.agents/scripts/lib/duplicate-search.js +242 -41
  91. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  92. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  93. package/.agents/scripts/lib/format-generated-json.js +97 -0
  94. package/.agents/scripts/lib/framework-version.js +19 -190
  95. package/.agents/scripts/lib/gh-exec.js +8 -0
  96. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  97. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
  98. package/.agents/scripts/lib/git-utils.js +32 -20
  99. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  100. package/.agents/scripts/lib/json-utils.js +1 -2
  101. package/.agents/scripts/lib/label-constants.js +10 -38
  102. package/.agents/scripts/lib/label-taxonomy.js +10 -55
  103. package/.agents/scripts/lib/observability/active-story-env.js +44 -165
  104. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  105. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  106. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  107. package/.agents/scripts/lib/observability/source-classifier.js +5 -5
  108. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  109. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  110. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  111. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  112. package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
  113. package/.agents/scripts/lib/orchestration/code-review.js +78 -436
  114. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  115. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
  116. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  117. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  118. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  119. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  120. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  121. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  122. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  123. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  124. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  125. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
  126. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  127. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  128. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  129. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
  130. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  131. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  132. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  133. package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
  134. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  135. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  136. package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
  137. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
  138. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
  139. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  140. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  141. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
  142. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
  143. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  144. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
  145. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
  146. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
  147. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  148. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  149. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  150. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +52 -51
  151. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  152. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
  153. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  154. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  155. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  156. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  157. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  158. package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
  159. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  160. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  161. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  162. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  163. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  164. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  165. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  166. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  167. package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
  168. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
  169. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  170. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  171. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
  172. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  173. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
  174. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  175. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  176. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
  177. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  178. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  179. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
  180. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  181. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  182. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  183. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  184. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  185. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  186. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  187. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
  188. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  189. package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
  190. package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
  191. package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
  192. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  193. package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
  194. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  195. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
  196. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
  197. package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
  198. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
  199. package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
  200. package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
  201. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  202. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  203. package/.agents/scripts/lib/planning-corpus.js +12 -281
  204. package/.agents/scripts/lib/preflight-runner.js +4 -4
  205. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  206. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  207. package/.agents/scripts/lib/signals/index.js +4 -17
  208. package/.agents/scripts/lib/signals/read.js +35 -35
  209. package/.agents/scripts/lib/signals/schema.js +8 -11
  210. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  211. package/.agents/scripts/lib/signals/write.js +0 -1
  212. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  213. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  214. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  215. package/.agents/scripts/lib/story-adjacency.js +17 -19
  216. package/.agents/scripts/lib/story-body/story-body.js +130 -75
  217. package/.agents/scripts/lib/story-plan.js +2 -4
  218. package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
  219. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  220. package/.agents/scripts/lib/test-env.js +14 -1
  221. package/.agents/scripts/lib/test-tiers.js +0 -3
  222. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
  223. package/.agents/scripts/lib/validation-evidence.js +32 -60
  224. package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
  225. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  226. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  227. package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
  228. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  229. package/.agents/scripts/lint-issue-body.js +71 -40
  230. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  231. package/.agents/scripts/notify.js +4 -3
  232. package/.agents/scripts/plan-context.js +102 -80
  233. package/.agents/scripts/plan-persist.js +230 -279
  234. package/.agents/scripts/plan-run-epilogue.js +142 -0
  235. package/.agents/scripts/post-structured-comment.js +0 -38
  236. package/.agents/scripts/pr-watch-with-update.js +43 -22
  237. package/.agents/scripts/providers/github/compose.js +0 -1
  238. package/.agents/scripts/providers/github/errors.js +0 -19
  239. package/.agents/scripts/providers/github/issues.js +13 -39
  240. package/.agents/scripts/providers/github/mappers.js +5 -12
  241. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  242. package/.agents/scripts/providers/github/tickets.js +33 -156
  243. package/.agents/scripts/providers/github.js +17 -6
  244. package/.agents/scripts/resolve-stories.js +236 -0
  245. package/.agents/scripts/run-coverage.js +4 -1
  246. package/.agents/scripts/run-lint.js +2 -2
  247. package/.agents/scripts/run-verify.js +31 -2
  248. package/.agents/scripts/signals-view.js +25 -21
  249. package/.agents/scripts/single-story-close.js +178 -26
  250. package/.agents/scripts/single-story-confirm-merge.js +313 -24
  251. package/.agents/scripts/single-story-init.js +35 -30
  252. package/.agents/scripts/stories-wave-tick.js +85 -10
  253. package/.agents/scripts/story-plan.js +28 -49
  254. package/.agents/scripts/update-ticket-state.js +14 -65
  255. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  256. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  257. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  258. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  259. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  260. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  261. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  262. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  263. package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
  264. package/.agents/skills/core/scope-triage/SKILL.md +31 -172
  265. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  266. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  267. package/.agents/skills/skills.index.json +3 -53
  268. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  269. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  270. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  271. package/.agents/starter-agentrc.json +0 -5
  272. package/.agents/templates/agent-protocol.md +9 -10
  273. package/.agents/workflows/audit-architecture.md +6 -7
  274. package/.agents/workflows/audit-clean-code.md +7 -7
  275. package/.agents/workflows/audit-dependencies.md +3 -3
  276. package/.agents/workflows/audit-devops.md +3 -3
  277. package/.agents/workflows/audit-documentation.md +9 -10
  278. package/.agents/workflows/audit-lighthouse.md +11 -3
  279. package/.agents/workflows/audit-navigability.md +13 -2
  280. package/.agents/workflows/audit-performance.md +5 -6
  281. package/.agents/workflows/audit-privacy.md +3 -3
  282. package/.agents/workflows/audit-quality.md +11 -12
  283. package/.agents/workflows/audit-security.md +4 -5
  284. package/.agents/workflows/audit-seo.md +13 -3
  285. package/.agents/workflows/audit-sre.md +3 -3
  286. package/.agents/workflows/audit-to-stories.md +20 -20
  287. package/.agents/workflows/audit-ux-ui.md +10 -3
  288. package/.agents/workflows/deliver.md +177 -176
  289. package/.agents/workflows/git-cleanup.md +5 -6
  290. package/.agents/workflows/git-deliver.md +1 -1
  291. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  292. package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
  293. package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
  294. package/.agents/workflows/helpers/code-review.md +75 -196
  295. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
  296. package/.agents/workflows/helpers/deliver-story.md +606 -0
  297. package/.agents/workflows/helpers/diagnose.md +10 -10
  298. package/.agents/workflows/helpers/parallel-tooling.md +3 -3
  299. package/.agents/workflows/helpers/signals.md +16 -16
  300. package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
  301. package/.agents/workflows/mandrel-update.md +2 -1
  302. package/.agents/workflows/plan.md +277 -145
  303. package/.agents/workflows/qa-assist.md +27 -33
  304. package/.agents/workflows/qa-explore.md +29 -38
  305. package/.agents/workflows/qa-run.md +2 -6
  306. package/README.md +9 -8
  307. package/bin/mandrel.js +12 -1
  308. package/docs/CHANGELOG.md +70 -0
  309. package/lib/cli/registry.js +262 -19
  310. package/lib/cli/sync-agents.js +157 -0
  311. package/lib/cli/sync-commands.js +115 -6
  312. package/lib/cli/sync.js +168 -6
  313. package/lib/cli/update.js +105 -8
  314. package/lib/cli/version-helpers.js +131 -0
  315. package/lib/migrations/README.md +7 -5
  316. package/lib/migrations/index.js +12 -8
  317. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  318. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  319. package/package.json +2 -2
  320. package/.agents/agents/retro.md +0 -42
  321. package/.agents/personas/architect.md +0 -113
  322. package/.agents/personas/devops-engineer.md +0 -38
  323. package/.agents/personas/engineer.md +0 -33
  324. package/.agents/personas/project-manager.md +0 -114
  325. package/.agents/personas/qa-engineer.md +0 -95
  326. package/.agents/personas/security-engineer.md +0 -111
  327. package/.agents/personas/technical-writer.md +0 -101
  328. package/.agents/schemas/dispatch-manifest.json +0 -232
  329. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  330. package/.agents/schemas/epic-spec.schema.json +0 -153
  331. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  332. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  333. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  334. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  335. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  336. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  337. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  338. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  339. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  340. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  341. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  342. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  343. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  344. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  345. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  346. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  347. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  348. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  349. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  350. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  351. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  352. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  353. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  354. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  355. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  356. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  357. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  358. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  359. package/.agents/schemas/risk-verdict.schema.json +0 -66
  360. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  361. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  362. package/.agents/scripts/analyze-execution.js +0 -444
  363. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  364. package/.agents/scripts/check-prepush-recovery.js +0 -90
  365. package/.agents/scripts/dispatcher.js +0 -295
  366. package/.agents/scripts/epic-audit-prepare.js +0 -497
  367. package/.agents/scripts/epic-audit-recheck.js +0 -274
  368. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  369. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  370. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  371. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  372. package/.agents/scripts/epic-plan-clarity.js +0 -211
  373. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  374. package/.agents/scripts/epic-reconcile.js +0 -625
  375. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  376. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  377. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  378. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  379. package/.agents/scripts/lib/config/preflight.js +0 -58
  380. package/.agents/scripts/lib/config/retro.js +0 -77
  381. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  382. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  383. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  384. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  385. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  386. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
  387. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  388. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  389. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  390. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
  391. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  392. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  393. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  394. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  395. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  396. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  397. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  398. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  399. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  400. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  401. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  402. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  403. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  404. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  405. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  406. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  407. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  408. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
  409. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  410. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  411. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  412. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  413. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  414. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  415. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  416. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  417. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  418. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  419. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  420. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  421. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  422. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  423. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  424. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  425. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  426. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
  427. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  428. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  429. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  430. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  431. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  432. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  433. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  434. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  435. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  436. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  437. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  438. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  439. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  440. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  441. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  442. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  443. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  444. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  445. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  446. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  447. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  448. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  449. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  450. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  451. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  452. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  453. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  454. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  455. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  456. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  457. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  458. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  459. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  460. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  461. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
  462. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  463. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  464. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  465. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
  466. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  467. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  468. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  469. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  470. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  471. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  472. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  473. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  474. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  475. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  476. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  477. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  478. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  479. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  480. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  481. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  482. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  483. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  484. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  485. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  486. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  487. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  488. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  489. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  490. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  491. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  492. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  493. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  494. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  495. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  496. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  497. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  498. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  499. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  500. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  501. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  502. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  503. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  504. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  505. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  506. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  507. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  508. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  509. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  510. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  511. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  512. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  513. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  514. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  515. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  516. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  517. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  518. package/.agents/scripts/lib/spec/index.js +0 -36
  519. package/.agents/scripts/lib/spec/loader.js +0 -425
  520. package/.agents/scripts/lib/spec/state.js +0 -208
  521. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  522. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  523. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  524. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  525. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  526. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  527. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  528. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  529. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  530. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  531. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  532. package/.agents/scripts/lifecycle-emit.js +0 -510
  533. package/.agents/scripts/retro-run.js +0 -218
  534. package/.agents/scripts/slice-phase.js +0 -361
  535. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  536. package/.agents/scripts/story-close.js +0 -294
  537. package/.agents/scripts/story-init.js +0 -599
  538. package/.agents/scripts/story-phase.js +0 -369
  539. package/.agents/scripts/wave-tick.js +0 -464
  540. package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
  541. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  542. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  543. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  544. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  545. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  546. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  547. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  548. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  549. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  550. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  551. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  552. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  553. package/.agents/workflows/helpers/epic-audit.md +0 -189
  554. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  555. package/.agents/workflows/helpers/epic-testing.md +0 -125
  556. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  557. package/.agents/workflows/helpers/plan-epic.md +0 -353
  558. package/.agents/workflows/helpers/plan-story.md +0 -251
  559. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  560. package/.agents/workflows/helpers/single-story-deliver.md +0 -557
@@ -0,0 +1,243 @@
1
+ /**
2
+ * runtime-friction.js — derive friction signals from observables the
3
+ * runtime already has (Story #4578).
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * Friction telemetry was **opt-in**: a `friction` record existed only when
8
+ * an agent volunteered a `diagnose-friction.js --story <id> --cmd <...>`
9
+ * call. `plan-run-epilogue.js`'s `follow-up-rollup` then read an empty
10
+ * `signals.ndjson` and truthfully reported "No friction signals — nothing
11
+ * to follow up". A 7-Story run containing a mid-run git outage, a parked
12
+ * worker needing an operator resume, and a four-round acceptance critic
13
+ * produced a **zero-signal retro** — because the stream is least likely to
14
+ * fill exactly when a run is going badly and the agent is busy.
15
+ *
16
+ * This module closes that gap from the other side: the runtime emits
17
+ * friction from what it *already knows*, at the point it already knows it.
18
+ * No agent cooperation required.
19
+ *
20
+ * ## Not a second channel
21
+ *
22
+ * These records go through the **existing** `appendSignal` path, carry the
23
+ * **existing** `kind: 'friction'` shape, and land in the **same**
24
+ * `signals.ndjson` stream `diagnose-friction.js` writes and the roll-up
25
+ * reads. The only thing that is new is *who* decides to write.
26
+ *
27
+ * Deliberately distinct from {@link ../gates/friction.js}'s
28
+ * `emitFrictionSignal`, which early-returns unless **both** `storyId` and
29
+ * `epicId` are truthy. Every v2 Story is standalone (`epicId: null` — see
30
+ * `temp-paths.storyTempDir`'s standalone branch), and the roll-up reads the
31
+ * standalone stream via `forEachLine(null, sid, ...)`. Routing runtime
32
+ * friction through the gate helper would drop **every** record on the floor,
33
+ * silently, which is the bug this Story exists to fix.
34
+ *
35
+ * ## Robustness contract
36
+ *
37
+ * Observability MUST NOT halt the runner (`signals-writer.js`; the
38
+ * `docs/patterns.md` friction pattern). Every export here is best-effort:
39
+ * it swallows its own failures after a `Logger.warn` and resolves `false`.
40
+ * A missing signal is strictly preferable to a broken close.
41
+ *
42
+ * @module lib/observability/runtime-friction
43
+ */
44
+
45
+ import crypto from 'node:crypto';
46
+
47
+ import { Logger } from '../Logger.js';
48
+ import { appendSignal } from './signals-writer.js';
49
+
50
+ /**
51
+ * The friction categories this module emits.
52
+ *
53
+ * Values are plain strings by design: `signal-event.schema.json` types
54
+ * `category` as a free-form `{ type: 'string', minLength: 1 }`, so no schema
55
+ * change is required to add one. They are frozen here so the emitters and
56
+ * their tests name the same literal instead of spreading it.
57
+ *
58
+ * Category choice is load-bearing for the retro: `retro-proposals.js`
59
+ * aggregates **by exact category string**, so these are deliberately coarse
60
+ * — one bucket per failure mode — rather than per-incident. Two Stories that
61
+ * hit the same wall in one run aggregate to `occurrences: 2` and route as a
62
+ * real proposal instead of being discarded as two unrelated singletons.
63
+ */
64
+ export const RUNTIME_FRICTION_CATEGORIES = Object.freeze({
65
+ /** A Story was parked at `agent::blocked` — the HITL pause (§ 1.J). */
66
+ STORY_BLOCKED: 'story-blocked',
67
+ /** A close run ended on a `failed` terminal (non-zero exit). */
68
+ CLOSE_FAILED: 'close-failed',
69
+ /** A bounded merge wait expired with the PR still in flight. */
70
+ MERGE_WAIT_EXHAUSTED: 'merge-wait-exhausted',
71
+ });
72
+
73
+ /** Cap on free-form reason text copied into a signal's `details`. */
74
+ const REASON_PREVIEW_LIMIT = 500;
75
+
76
+ /**
77
+ * @param {unknown} value
78
+ * @returns {string}
79
+ */
80
+ function preview(value) {
81
+ return String(value ?? '').slice(0, REASON_PREVIEW_LIMIT);
82
+ }
83
+
84
+ /**
85
+ * @param {unknown} value
86
+ * @returns {number|null}
87
+ */
88
+ function positiveIntOrNull(value) {
89
+ const n = Number(value);
90
+ return Number.isInteger(n) && n > 0 ? n : null;
91
+ }
92
+
93
+ /**
94
+ * Append one runtime-derived `friction` record to the Story's signals
95
+ * stream. Best-effort: never throws, never rejects.
96
+ *
97
+ * `epicId` defaults to `null` (the standalone-Story stream) because that is
98
+ * where v2 Stories live and where the roll-up reads.
99
+ *
100
+ * @param {object} args
101
+ * @param {number} args.storyId
102
+ * @param {number|null} [args.epicId]
103
+ * @param {string} args.category One of {@link RUNTIME_FRICTION_CATEGORIES}.
104
+ * @param {string} args.tool Emitting surface, for `emitter.tool`.
105
+ * @param {object} [args.details] Kind-specific payload (always an object).
106
+ * @param {object} [args.config] Resolved config (for `tempRoot`).
107
+ * @returns {Promise<boolean>} true when a record was appended.
108
+ */
109
+ export async function emitRuntimeFriction({
110
+ storyId,
111
+ epicId = null,
112
+ category,
113
+ tool,
114
+ details = {},
115
+ config,
116
+ } = {}) {
117
+ const sid = positiveIntOrNull(storyId);
118
+ if (sid === null) {
119
+ // No Story context → no stream to write to. Not an error: some close
120
+ // paths (a usage error before the id is parsed) genuinely have none.
121
+ return false;
122
+ }
123
+ if (typeof category !== 'string' || category.trim() === '') {
124
+ Logger.warn('[runtime-friction] refusing to emit a category-less signal');
125
+ return false;
126
+ }
127
+
128
+ const signal = {
129
+ kind: 'friction',
130
+ eventId: crypto.randomUUID(),
131
+ ts: new Date().toISOString(),
132
+ epicId: positiveIntOrNull(epicId),
133
+ storyId: sid,
134
+ // 2-tier hierarchy (Epic #3163): no Task tier. Retained for schema
135
+ // compatibility and always null — mirrors diagnose-friction.js.
136
+ taskId: null,
137
+ category: category.trim(),
138
+ emitter: { tool: tool || 'runtime-friction' },
139
+ details: details && typeof details === 'object' ? details : {},
140
+ };
141
+
142
+ try {
143
+ return await appendSignal({
144
+ epicId: signal.epicId,
145
+ storyId: sid,
146
+ signal,
147
+ config,
148
+ });
149
+ } catch (err) {
150
+ // `appendSignal` already swallows its own I/O failures; this catch is
151
+ // defense in depth so a surprise (a poisoned config, a throwing
152
+ // validator) still cannot take down the path being observed.
153
+ Logger.warn(
154
+ `[runtime-friction] append failed for Story #${sid} (${category}): ${
155
+ err instanceof Error ? err.message : String(err)
156
+ }`,
157
+ );
158
+ return false;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Decide whether a `story-deliver-terminal` envelope is worth a friction
164
+ * record, and describe it. **Pure** — no I/O — so the (interesting) policy
165
+ * is unit-testable without touching disk.
166
+ *
167
+ * The partition is deliberate; each observable is emitted from exactly ONE
168
+ * place, so one incident never double-counts into `occurrences: 2` and
169
+ * fabricates a filed proposal out of a single event:
170
+ *
171
+ * - `blocked` → **null here.** Every blocked terminal flips the Story to
172
+ * `agent::blocked` (`confirm-merge.js`, both the `merge.unlanded` and
173
+ * `merge.flip-failed` paths), and that transition is instrumented at the
174
+ * canonical mutator (`ticketing/transition.js`). Emitting here as well
175
+ * would count the same block twice.
176
+ * - `landed` → null. Nothing happened worth a retro.
177
+ * - `failed` → friction. A close that ended non-zero.
178
+ * - `pending` → friction **only when a `waitBudget` was exhausted**. That
179
+ * is the parked worker from the report: a bounded wait expired with the
180
+ * PR in flight and a human must resume it. A `pending` with **no**
181
+ * `waitBudget` is the `--no-wait-merge` / operator-merge path, where the
182
+ * human deliberately owns the land and nothing is broken — flagging it
183
+ * would train operators to ignore the channel.
184
+ *
185
+ * Deliberately **not exported**: it is this module's internal policy, and
186
+ * `emitTerminalFriction` is the contract callers (and tests) exercise. An
187
+ * export solely for testability would be production-dead code — the
188
+ * `--production` dead-exports ratchet exists to catch exactly that.
189
+ *
190
+ * @param {object} envelope A `story-deliver-terminal` envelope.
191
+ * @returns {{ category: string, details: object }|null}
192
+ */
193
+ function frictionForTerminal(envelope) {
194
+ if (!envelope || typeof envelope !== 'object') return null;
195
+ const { status, phase, waitBudget, failure, pr } = envelope;
196
+
197
+ if (status === 'failed') {
198
+ return {
199
+ category: RUNTIME_FRICTION_CATEGORIES.CLOSE_FAILED,
200
+ details: {
201
+ phase: phase ?? null,
202
+ reason: preview(failure?.reason),
203
+ },
204
+ };
205
+ }
206
+
207
+ if (status === 'pending' && waitBudget) {
208
+ return {
209
+ category: RUNTIME_FRICTION_CATEGORIES.MERGE_WAIT_EXHAUSTED,
210
+ details: {
211
+ phase: phase ?? null,
212
+ prNumber: pr?.number ?? null,
213
+ checksStatus: pr?.checksStatus ?? null,
214
+ waitedSeconds: waitBudget.waitedSeconds ?? null,
215
+ cumulativeSeconds: waitBudget.cumulativeSeconds ?? null,
216
+ maxBudgetSeconds: waitBudget.maxBudgetSeconds ?? null,
217
+ },
218
+ };
219
+ }
220
+
221
+ return null;
222
+ }
223
+
224
+ /**
225
+ * Emit the friction record (if any) implied by a terminal envelope.
226
+ * Best-effort; never throws.
227
+ *
228
+ * @param {object} args
229
+ * @param {object} args.envelope
230
+ * @param {object} [args.config]
231
+ * @returns {Promise<boolean>} true when a record was appended.
232
+ */
233
+ export async function emitTerminalFriction({ envelope, config } = {}) {
234
+ const verdict = frictionForTerminal(envelope);
235
+ if (!verdict) return false;
236
+ return emitRuntimeFriction({
237
+ storyId: envelope?.storyId,
238
+ category: verdict.category,
239
+ tool: 'single-story-close',
240
+ details: verdict.details,
241
+ config,
242
+ });
243
+ }
@@ -18,7 +18,7 @@
18
18
  * other draft-07 validators (see `tests/schemas/signal-schemas.test.js`).
19
19
  *
20
20
  * A per-Epic reject tally is persisted under the Epic temp tree
21
- * (`temp/epic-<eid>/signal-rejects.json`) so a cross-process reader (the
21
+ * (`temp/run-<eid>/signal-rejects.json`) so a cross-process reader (the
22
22
  * loop-health check, a follow-on Story) can surface how many records were
23
23
  * dropped. The tally is read-modify-written best-effort; a lost increment
24
24
  * under a write race is acceptable for a diagnostic counter.
@@ -32,7 +32,7 @@ import { fileURLToPath } from 'node:url';
32
32
  import Ajv from 'ajv';
33
33
  import addFormats from 'ajv-formats';
34
34
 
35
- import { epicArtifactPath } from '../config/temp-paths.js';
35
+ import { runArtifactPath } from '../config/temp-paths.js';
36
36
  import { Logger } from '../Logger.js';
37
37
 
38
38
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -141,7 +141,7 @@ export async function recordSignalReject({ epicId, config, field }) {
141
141
  if (!Number.isInteger(epicId) || epicId <= 0) return null;
142
142
  let target;
143
143
  try {
144
- target = epicArtifactPath(epicId, REJECT_TALLY_BASENAME, config);
144
+ target = runArtifactPath(epicId, REJECT_TALLY_BASENAME, config);
145
145
  } catch {
146
146
  return null;
147
147
  }
@@ -190,7 +190,7 @@ export async function readSignalRejectCount({ epicId, config }) {
190
190
  if (!Number.isInteger(epicId) || epicId <= 0) return 0;
191
191
  let target;
192
192
  try {
193
- target = epicArtifactPath(epicId, REJECT_TALLY_BASENAME, config);
193
+ target = runArtifactPath(epicId, REJECT_TALLY_BASENAME, config);
194
194
  } catch {
195
195
  return 0;
196
196
  }
@@ -2,7 +2,7 @@
2
2
  * Append-only signals/trace writer (Epic #1030 Story #1041).
3
3
  *
4
4
  * Centralizes the per-(epic, story) NDJSON streams under
5
- * `temp/epic-<eid>/stories/story-<sid>/signals.ndjson` (and a sibling
5
+ * `temp/run-<id>/stories/story-<sid>/signals.ndjson` (and a sibling
6
6
  * `traces.ndjson` for trace-shaped records). Detector modules and the
7
7
  * runtime trace hook all funnel through this writer so the on-disk
8
8
  * shape stays under one schema and one set of robustness guarantees.
@@ -18,7 +18,7 @@
18
18
  * fire from inside per-Story sub-agents that may exit abruptly, and
19
19
  * a buffered tail would silently disappear on `process.exit`.
20
20
  * - **Lazy directory creation.** The first write to a fresh Story
21
- * creates `temp/epic-<eid>/stories/story-<sid>/` via `fs.mkdir(..., { recursive: true })`.
21
+ * creates `temp/run-<id>/stories/story-<sid>/` via `fs.mkdir(..., { recursive: true })`.
22
22
  * `epicId` / `storyId` are required positive integers — the
23
23
  * `temp-paths.js` helpers assert this before we touch the disk.
24
24
  *
@@ -36,17 +36,12 @@ import fs from 'node:fs/promises';
36
36
  import path from 'node:path';
37
37
  import { createInterface } from 'node:readline';
38
38
 
39
- import {
40
- epicArtifactPath,
41
- signalsFile,
42
- storyTempDir,
43
- } from '../config/temp-paths.js';
39
+ import { signalsFile, storyTempDir } from '../config/temp-paths.js';
44
40
  import { Logger } from '../Logger.js';
45
41
  import { recordSignalReject, validateSignal } from './signal-validator.js';
46
42
  import { classifyPathSource } from './source-classifier.js';
47
43
 
48
44
  const TRACES_BASENAME = 'traces.ndjson';
49
- const EPIC_SIGNALS_BASENAME = 'signals.ndjson';
50
45
 
51
46
  /**
52
47
  * Async traces-file path (kept private — consumers thread through
@@ -167,7 +162,7 @@ async function appendOne(targetPath, record) {
167
162
  }
168
163
 
169
164
  /**
170
- * Append one signal record to `temp/epic-<eid>/stories/story-<sid>/signals.ndjson`.
165
+ * Append one signal record to `temp/run-<id>/stories/story-<sid>/signals.ndjson`.
171
166
  *
172
167
  * The `signal` is written verbatim — callers (detectors) own its shape
173
168
  * (kind, severity, message, etc.). The writer adds nothing. Errors are
@@ -200,42 +195,7 @@ export async function appendSignal(args) {
200
195
  }
201
196
 
202
197
  /**
203
- * Append one signal record to the per-Epic stream at
204
- * `temp/epic-<eid>/signals.ndjson` — used for Epic-scoped signals not tied
205
- * to an individual Story: the wave-window forensics kinds (`wave-start`,
206
- * `wave-complete`), notification-derived anchors (`state-transition`,
207
- * `notification.emitted`), and Epic-level `friction` (e.g.
208
- * `lifecycle-emit.js`). The retired write-only kinds `wave-tick` /
209
- * `epic-complete` are gone (Story #3909) and are NOT valid here.
210
- *
211
- * @param {{ epicId: number, signal: unknown, config?: object }} args
212
- * @returns {Promise<boolean>}
213
- */
214
- export async function appendEpicSignal(args) {
215
- const { epicId, signal, config } = args ?? {};
216
- let target;
217
- try {
218
- target = epicArtifactPath(epicId, EPIC_SIGNALS_BASENAME, config);
219
- } catch (err) {
220
- Logger.warn(
221
- `signals-writer: invalid epicId for appendEpicSignal: ${
222
- err instanceof Error ? err.message : String(err)
223
- }`,
224
- );
225
- return false;
226
- }
227
- const tagged = tagSignalSource(signal);
228
- const ok = await validateOrDrop(tagged, {
229
- epicId: Number.isInteger(epicId) ? epicId : null,
230
- config,
231
- label: 'epic signal',
232
- });
233
- if (!ok) return false;
234
- return appendOne(target, tagged);
235
- }
236
-
237
- /**
238
- * Append one trace record to `temp/epic-<eid>/stories/story-<sid>/traces.ndjson`.
198
+ * Append one trace record to `temp/run-<id>/stories/story-<sid>/traces.ndjson`.
239
199
  * Same robustness contract as `appendSignal` — never throws.
240
200
  *
241
201
  * @param {{ epicId: number, storyId: number, trace: unknown, config?: object }} args
@@ -270,7 +230,7 @@ export async function appendTrace(args) {
270
230
  * lines are skipped with a `Logger.warn`. A missing file resolves with
271
231
  * `missing: true` rather than throwing.
272
232
  *
273
- * Shared spine for `forEachLine` (per-Story stream) and `forEachEpicLine`
233
+ * Shared spine for `forEachLine`
274
234
  * (per-Epic stream) so the two readers cannot drift in their
275
235
  * malformed-line / missing-file / cb-throw handling.
276
236
  *
@@ -361,39 +321,3 @@ export async function forEachLine(epicId, storyId, cb, config) {
361
321
 
362
322
  return forEachLineIn(target, cb, 'forEachLine');
363
323
  }
364
-
365
- /**
366
- * Stream the per-Epic `signals.ndjson` line by line, invoking
367
- * `cb(parsed, lineNumber)` for each successfully parsed JSON line. This is
368
- * the read side of `appendEpicSignal` — the wave-lifecycle stream at
369
- * `temp/epic-<eid>/signals.ndjson` written by `appendEpicSignal` callers
370
- * (e.g. `lifecycle-emit`). A missing file resolves with `missing: true`
371
- * rather than throwing, mirroring the per-Story `forEachLine` contract so
372
- * the retro's unified counts scan can fold the Epic stream in alongside the
373
- * Story streams without a special-cased absence branch.
374
- *
375
- * @param {number} epicId
376
- * @param {(parsed: unknown, lineNumber: number) => unknown | Promise<unknown>} cb
377
- * @param {object} [config]
378
- * @returns {Promise<{ linesRead: number, linesParsed: number, missing: boolean }>}
379
- */
380
- export async function forEachEpicLine(epicId, cb, config) {
381
- if (typeof cb !== 'function') {
382
- Logger.warn('signals-writer: forEachEpicLine called without a callback');
383
- return { linesRead: 0, linesParsed: 0, missing: false };
384
- }
385
-
386
- let target;
387
- try {
388
- target = epicArtifactPath(epicId, EPIC_SIGNALS_BASENAME, config);
389
- } catch (err) {
390
- Logger.warn(
391
- `signals-writer: invalid epicId for forEachEpicLine: ${
392
- err instanceof Error ? err.message : String(err)
393
- }`,
394
- );
395
- return { linesRead: 0, linesParsed: 0, missing: false };
396
- }
397
-
398
- return forEachLineIn(target, cb, 'forEachEpicLine');
399
- }
@@ -4,8 +4,8 @@
4
4
  * `"consumer"` (the host project that consumes the framework via the
5
5
  * materialized `.agents/` directory).
6
6
  *
7
- * Used by `signals-writer.js#appendSignal` / `appendEpicSignal` so every
8
- * record in `temp/epic-<eid>/stories/story-<sid>/signals.ndjson` carries an
7
+ * Used by `signals-writer.js#appendSignal` so every
8
+ * record in `temp/run-<id>/stories/story-<sid>/signals.ndjson` carries an
9
9
  * authoritative `source` field, allowing downstream retro consumers to
10
10
  * route framework signals back to mandrel and keep consumer signals in
11
11
  * the host project (Epic #2547 / Story #2553).
@@ -57,7 +57,7 @@ function toScanString(value) {
57
57
  /**
58
58
  * Return true when `haystack` contains any framework prefix as a
59
59
  * substring. We use `includes` (not `startsWith`) because a command line
60
- * like `node .agents/scripts/story-init.js` carries the prefix in the
60
+ * like `node .agents/scripts/single-story-init.js` carries the prefix in the
61
61
  * middle, and a failing-path like `repo/.agents/foo.js` may carry an
62
62
  * absolute prefix.
63
63
  *
@@ -83,13 +83,13 @@ function containsFrameworkPrefix(haystack) {
83
83
  * Framework-wins: if either input matches a framework prefix, the result
84
84
  * is `"framework"` even when the other input looks consumer-shaped. This
85
85
  * matters for mixed cases like a consumer test invoking
86
- * `node .agents/scripts/story-init.js` — that's framework friction even
86
+ * `node .agents/scripts/single-story-init.js` — that's framework friction even
87
87
  * though the failing test path lives under the consumer.
88
88
  *
89
89
  * @param {unknown} failingPath The path of the file or directory the
90
90
  * signal blames (e.g. `"tests/foo.test.js"`).
91
91
  * @param {unknown} command The command line the signal blames
92
- * (e.g. `"node .agents/scripts/story-init.js"`).
92
+ * (e.g. `"node .agents/scripts/single-story-init.js"`).
93
93
  * @returns {"framework"|"consumer"}
94
94
  */
95
95
  export function classifyPathSource(failingPath, command) {
@@ -5,7 +5,7 @@
5
5
  * PostToolUse hook entries. Resolves the active Epic + Story from
6
6
  * environment variables (`CC_EPIC_ID` / `CC_STORY_ID`), pairs Pre/Post
7
7
  * tool-call events, and appends one `kind:"trace"` NDJSON line per tool
8
- * call to `temp/epic-<eid>/stories/story-<sid>/traces.ndjson` via the
8
+ * call to `temp/run-<id>/stories/story-<sid>/traces.ndjson` via the
9
9
  * `signals-writer.appendTrace` helper.
10
10
  *
11
11
  * Robustness contract (Tech Spec #1032 §observability + §security):
@@ -48,7 +48,6 @@
48
48
 
49
49
  import { createHash } from 'node:crypto';
50
50
 
51
- import { emitHeartbeatFromHook } from './hook-heartbeat.js';
52
51
  import { appendTrace } from './signals-writer.js';
53
52
 
54
53
  /**
@@ -388,19 +387,10 @@ export async function main(event) {
388
387
  const phase = event.hook_event_name;
389
388
  if (phase === 'PreToolUse') {
390
389
  // Pre-pairing only matters for the trace-line duration, which only
391
- // the Story-scoped trace path records; slice-only context (single
392
- // delivery) needs no Pre.
390
+ // the Story-scoped trace path records.
393
391
  if (active) handlePre(event);
394
392
  } else if (phase === 'PostToolUse') {
395
393
  if (active) await handlePost(event, active);
396
- // Heartbeat OFF the token stream (Epic #4476 M5). A throttled
397
- // story.heartbeat / slice.heartbeat, keyed off the same active-Story /
398
- // active-slice env vars, so the §2e Idle Watchdog's forward-progress
399
- // signal is a free byproduct of ANY tool call — no dedicated
400
- // bookkeeping LLM turn. Best-effort and self-guarded; resolves its own
401
- // target (fires for slice context even when `active` is null because
402
- // there is no CC_STORY_ID under single delivery).
403
- emitHeartbeatFromHook();
404
394
  }
405
395
  // Any other phase is silently ignored — the hook is registered for
406
396
  // Pre/Post only; receiving anything else is a configuration error
@@ -37,9 +37,7 @@ import { STUB_MARKER, scaffoldDocs } from './scaffold-docs.js';
37
37
  */
38
38
  export const PLAN_HANDOFF_TEXT =
39
39
  '\n✅ Mandrel is ready. Start your first project:\n\n' +
40
- ' /plan --idea "<one-line description of what you want to build>"\n\n' +
41
- 'Or, if you already have a `type::epic` Issue open:\n\n' +
42
- ' /plan <epicId>\n';
40
+ ' /plan --seed "<one-line description of what you want to build>"\n';
43
41
 
44
42
  // ---------------------------------------------------------------------------
45
43
  // Internal helpers
@@ -15,7 +15,7 @@
15
15
  * hard-clamped to `[1, 8]`), and the executor spawns ONE maker-blind
16
16
  * fresh-context `Agent` critic per cluster. The cluster count is therefore
17
17
  * `ceil(totalACs / clusterCeiling)` — a deterministic fan-out width the
18
- * `deliver-epic-single.md` executor and its isolation test both key off.
18
+ * consuming executor and its isolation test both key off.
19
19
  *
20
20
  * Pure and total — inputs in, clusters out. No I/O, no throws on malformed
21
21
  * input (a non-array / empty AC set yields zero clusters — the executor then
@@ -41,7 +41,7 @@
41
41
 
42
42
  import { readFileSync } from 'node:fs';
43
43
 
44
- import { epicArtifactPath, signalsFile } from '../config/temp-paths.js';
44
+ import { runArtifactPath, signalsFile } from '../config/temp-paths.js';
45
45
 
46
46
  /** Epic-level signals stream basename (mirrors signals-writer). */
47
47
  const EPIC_SIGNALS_BASENAME = 'signals.ndjson';
@@ -231,7 +231,7 @@ export function deriveAcceptanceEvalRound({
231
231
  readFile = (p) => readFileSync(p, 'utf8'),
232
232
  signalsPathResolver = signalsFile,
233
233
  epicSignalsPathResolver = (eid, cfg) =>
234
- epicArtifactPath(eid, EPIC_SIGNALS_BASENAME, cfg),
234
+ runArtifactPath(eid, EPIC_SIGNALS_BASENAME, cfg),
235
235
  }) {
236
236
  // Epic #4475 (M4-B): single-delivery critics score AC clusters, not
237
237
  // Stories. When `clusterId` is supplied the round is counted per cluster