mandrel 1.57.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 (843) hide show
  1. package/.agents/README.md +954 -0
  2. package/.agents/docs/SDLC.md +1420 -0
  3. package/.agents/docs/agentrc-reference.json +278 -0
  4. package/.agents/docs/configuration.md +1040 -0
  5. package/.agents/docs/workflows.md +59 -0
  6. package/.agents/instructions.md +384 -0
  7. package/.agents/personas/architect.md +107 -0
  8. package/.agents/personas/devops-engineer.md +36 -0
  9. package/.agents/personas/engineer-mobile.md +119 -0
  10. package/.agents/personas/engineer-web.md +110 -0
  11. package/.agents/personas/engineer.md +90 -0
  12. package/.agents/personas/product.md +88 -0
  13. package/.agents/personas/project-manager.md +110 -0
  14. package/.agents/personas/qa-engineer.md +91 -0
  15. package/.agents/personas/refactorer.md +110 -0
  16. package/.agents/personas/security-engineer.md +112 -0
  17. package/.agents/personas/sre.md +86 -0
  18. package/.agents/personas/technical-writer.md +100 -0
  19. package/.agents/personas/ux-designer.md +95 -0
  20. package/.agents/rules/api-conventions.md +75 -0
  21. package/.agents/rules/changelog-style.md +238 -0
  22. package/.agents/rules/gherkin-standards.md +146 -0
  23. package/.agents/rules/git-conventions.md +146 -0
  24. package/.agents/rules/orchestration-error-handling.md +35 -0
  25. package/.agents/rules/security-baseline.md +92 -0
  26. package/.agents/rules/shell-conventions.md +70 -0
  27. package/.agents/rules/test-seams.md +59 -0
  28. package/.agents/rules/testing-standards.md +177 -0
  29. package/.agents/runtime-deps.json +18 -0
  30. package/.agents/schemas/acceptance-eval-verdict.schema.json +93 -0
  31. package/.agents/schemas/agentrc.schema.json +1583 -0
  32. package/.agents/schemas/audit-results.schema.json +69 -0
  33. package/.agents/schemas/audit-rules.json +134 -0
  34. package/.agents/schemas/audit-rules.schema.json +69 -0
  35. package/.agents/schemas/baselines/baseline-envelope.schema.json +44 -0
  36. package/.agents/schemas/baselines/bundle-size.schema.json +47 -0
  37. package/.agents/schemas/baselines/coverage.schema.json +50 -0
  38. package/.agents/schemas/baselines/crap.schema.json +52 -0
  39. package/.agents/schemas/baselines/duplication.schema.json +62 -0
  40. package/.agents/schemas/baselines/lighthouse.schema.json +59 -0
  41. package/.agents/schemas/baselines/lint.schema.json +47 -0
  42. package/.agents/schemas/baselines/maintainability.schema.json +71 -0
  43. package/.agents/schemas/baselines/mutation.schema.json +52 -0
  44. package/.agents/schemas/crap-baseline.schema.json +57 -0
  45. package/.agents/schemas/crap-report.schema.json +102 -0
  46. package/.agents/schemas/dispatch-manifest.json +232 -0
  47. package/.agents/schemas/epic-perf-report.schema.json +89 -0
  48. package/.agents/schemas/epic-spec.schema.json +183 -0
  49. package/.agents/schemas/friction-event.schema.json +56 -0
  50. package/.agents/schemas/lifecycle/README.md +18 -0
  51. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +13 -0
  52. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +13 -0
  53. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +13 -0
  54. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +12 -0
  55. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +13 -0
  56. package/.agents/schemas/lifecycle/checkpoint.written.schema.json +13 -0
  57. package/.agents/schemas/lifecycle/close-validate.end.schema.json +18 -0
  58. package/.agents/schemas/lifecycle/close-validate.start.schema.json +13 -0
  59. package/.agents/schemas/lifecycle/code-review.end.schema.json +30 -0
  60. package/.agents/schemas/lifecycle/code-review.start.schema.json +12 -0
  61. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +14 -0
  62. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +13 -0
  63. package/.agents/schemas/lifecycle/epic.blocked.schema.json +13 -0
  64. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +12 -0
  65. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +12 -0
  66. package/.agents/schemas/lifecycle/epic.close.end.schema.json +12 -0
  67. package/.agents/schemas/lifecycle/epic.complete.schema.json +13 -0
  68. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +13 -0
  69. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +12 -0
  70. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +13 -0
  71. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +14 -0
  72. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +17 -0
  73. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +15 -0
  74. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +18 -0
  75. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +12 -0
  76. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +16 -0
  77. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +12 -0
  78. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +28 -0
  79. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +16 -0
  80. package/.agents/schemas/lifecycle/intervention.recorded.schema.json +15 -0
  81. package/.agents/schemas/lifecycle/ledger-record.schema.json +59 -0
  82. package/.agents/schemas/lifecycle/notification.emitted.schema.json +18 -0
  83. package/.agents/schemas/lifecycle/pr.created.schema.json +14 -0
  84. package/.agents/schemas/lifecycle/retro.end.schema.json +16 -0
  85. package/.agents/schemas/lifecycle/retro.start.schema.json +12 -0
  86. package/.agents/schemas/lifecycle/story.blocked.schema.json +13 -0
  87. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +17 -0
  88. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +15 -0
  89. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +20 -0
  90. package/.agents/schemas/lifecycle/story.merged.schema.json +13 -0
  91. package/.agents/schemas/mi-report.schema.json +58 -0
  92. package/.agents/schemas/model-attribution.schema.json +49 -0
  93. package/.agents/schemas/qa-finding.schema.json +133 -0
  94. package/.agents/schemas/qa-ledger.schema.json +89 -0
  95. package/.agents/schemas/risk-verdict.schema.json +53 -0
  96. package/.agents/schemas/signal-event.schema.json +58 -0
  97. package/.agents/schemas/skill.schema.json +31 -0
  98. package/.agents/schemas/skills-index.schema.json +81 -0
  99. package/.agents/schemas/story-perf-summary.schema.json +73 -0
  100. package/.agents/schemas/validation-evidence.schema.json +78 -0
  101. package/.agents/scripts/README.md +93 -0
  102. package/.agents/scripts/acceptance-eval.js +284 -0
  103. package/.agents/scripts/acceptance-spec-reconciler.js +556 -0
  104. package/.agents/scripts/agents-bootstrap-github.js +634 -0
  105. package/.agents/scripts/analyze-execution.js +369 -0
  106. package/.agents/scripts/assert-branch.js +83 -0
  107. package/.agents/scripts/audit-labels-bootstrap.js +253 -0
  108. package/.agents/scripts/audit-to-stories.js +257 -0
  109. package/.agents/scripts/bootstrap.js +1378 -0
  110. package/.agents/scripts/check-baselines.js +81 -0
  111. package/.agents/scripts/check-dead-exports.js +311 -0
  112. package/.agents/scripts/check-doc-links.js +401 -0
  113. package/.agents/scripts/check-gherkin-placeholders.js +663 -0
  114. package/.agents/scripts/check-lifecycle-doc-drift.js +402 -0
  115. package/.agents/scripts/check-lifecycle-lint.js +379 -0
  116. package/.agents/scripts/check-prepush-recovery.js +90 -0
  117. package/.agents/scripts/check-windows-git-perf.js +138 -0
  118. package/.agents/scripts/cleanup-repo-test-temp.js +67 -0
  119. package/.agents/scripts/coverage-capture.js +112 -0
  120. package/.agents/scripts/detect-merges.js +111 -0
  121. package/.agents/scripts/diagnose-friction.js +257 -0
  122. package/.agents/scripts/diagnose.js +240 -0
  123. package/.agents/scripts/dispatcher.js +295 -0
  124. package/.agents/scripts/drain-pending-cleanup.js +147 -0
  125. package/.agents/scripts/epic-audit-prepare.js +419 -0
  126. package/.agents/scripts/epic-audit-recheck.js +241 -0
  127. package/.agents/scripts/epic-deliver-note-intervention.js +192 -0
  128. package/.agents/scripts/epic-deliver-preflight.js +407 -0
  129. package/.agents/scripts/epic-deliver-prepare.js +383 -0
  130. package/.agents/scripts/epic-execute-record-wave.js +463 -0
  131. package/.agents/scripts/epic-plan-clarity.js +201 -0
  132. package/.agents/scripts/epic-plan-decompose.js +79 -0
  133. package/.agents/scripts/epic-plan-healthcheck.js +363 -0
  134. package/.agents/scripts/epic-plan-spec-validate.js +111 -0
  135. package/.agents/scripts/epic-plan-spec.js +198 -0
  136. package/.agents/scripts/epic-reconcile.js +637 -0
  137. package/.agents/scripts/evidence-gate.js +235 -0
  138. package/.agents/scripts/generate-config-docs.js +516 -0
  139. package/.agents/scripts/generate-lifecycle-docs.js +224 -0
  140. package/.agents/scripts/generate-skills-index.js +252 -0
  141. package/.agents/scripts/generate-workflows-doc.js +168 -0
  142. package/.agents/scripts/git-cleanup.js +124 -0
  143. package/.agents/scripts/git-pr-quality-gate.js +203 -0
  144. package/.agents/scripts/git-rebase-and-resolve.js +234 -0
  145. package/.agents/scripts/hierarchy-gate.js +176 -0
  146. package/.agents/scripts/hydrate-context.js +179 -0
  147. package/.agents/scripts/install-matrix-assert.js +282 -0
  148. package/.agents/scripts/lib/Graph.js +326 -0
  149. package/.agents/scripts/lib/ITicketingProvider.js +349 -0
  150. package/.agents/scripts/lib/Logger.js +194 -0
  151. package/.agents/scripts/lib/audit-suite/cli.js +64 -0
  152. package/.agents/scripts/lib/audit-suite/findings.js +164 -0
  153. package/.agents/scripts/lib/audit-suite/frontmatter-lint.js +32 -0
  154. package/.agents/scripts/lib/audit-suite/frontmatter.js +110 -0
  155. package/.agents/scripts/lib/audit-suite/index.js +22 -0
  156. package/.agents/scripts/lib/audit-suite/runner.js +233 -0
  157. package/.agents/scripts/lib/audit-suite/selector.js +235 -0
  158. package/.agents/scripts/lib/audit-suite/substitutions.js +124 -0
  159. package/.agents/scripts/lib/audit-suite/workflow-loader.js +49 -0
  160. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +130 -0
  161. package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +114 -0
  162. package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +93 -0
  163. package/.agents/scripts/lib/audit-to-stories/group-findings.js +265 -0
  164. package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +246 -0
  165. package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +160 -0
  166. package/.agents/scripts/lib/auto-refresh-baselines.js +308 -0
  167. package/.agents/scripts/lib/baseline-loader.js +0 -0
  168. package/.agents/scripts/lib/baseline-schema-registry.js +69 -0
  169. package/.agents/scripts/lib/baseline-snapshot.js +716 -0
  170. package/.agents/scripts/lib/baselines/component-matcher.js +21 -0
  171. package/.agents/scripts/lib/baselines/components.js +126 -0
  172. package/.agents/scripts/lib/baselines/diff-scope-cli.js +203 -0
  173. package/.agents/scripts/lib/baselines/duplication-scanner.js +220 -0
  174. package/.agents/scripts/lib/baselines/env-overrides.js +129 -0
  175. package/.agents/scripts/lib/baselines/envelope.js +368 -0
  176. package/.agents/scripts/lib/baselines/exit-codes.js +89 -0
  177. package/.agents/scripts/lib/baselines/git-base.js +0 -0
  178. package/.agents/scripts/lib/baselines/kernel.js +111 -0
  179. package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +220 -0
  180. package/.agents/scripts/lib/baselines/kinds/bundle-size.js +157 -0
  181. package/.agents/scripts/lib/baselines/kinds/coverage.js +194 -0
  182. package/.agents/scripts/lib/baselines/kinds/crap.js +555 -0
  183. package/.agents/scripts/lib/baselines/kinds/duplication.js +197 -0
  184. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +185 -0
  185. package/.agents/scripts/lib/baselines/kinds/lint.js +172 -0
  186. package/.agents/scripts/lib/baselines/kinds/maintainability.js +340 -0
  187. package/.agents/scripts/lib/baselines/kinds/mutation.js +153 -0
  188. package/.agents/scripts/lib/baselines/path-canon.js +279 -0
  189. package/.agents/scripts/lib/baselines/preview-gates.js +298 -0
  190. package/.agents/scripts/lib/baselines/reader.js +321 -0
  191. package/.agents/scripts/lib/baselines/refresh-service.js +733 -0
  192. package/.agents/scripts/lib/baselines/scope.js +291 -0
  193. package/.agents/scripts/lib/baselines/writer.js +312 -0
  194. package/.agents/scripts/lib/bdd-runner-detect.js +417 -0
  195. package/.agents/scripts/lib/bdd-scenario-scanner.js +310 -0
  196. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +202 -0
  197. package/.agents/scripts/lib/bootstrap/branch-protection.js +222 -0
  198. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +171 -0
  199. package/.agents/scripts/lib/bootstrap/commit-push.js +146 -0
  200. package/.agents/scripts/lib/bootstrap/gh-list.js +153 -0
  201. package/.agents/scripts/lib/bootstrap/gh-preflight.js +306 -0
  202. package/.agents/scripts/lib/bootstrap/hitl-confirm.js +89 -0
  203. package/.agents/scripts/lib/bootstrap/install-ledger.js +174 -0
  204. package/.agents/scripts/lib/bootstrap/manifest.js +272 -0
  205. package/.agents/scripts/lib/bootstrap/merge-methods.js +108 -0
  206. package/.agents/scripts/lib/bootstrap/preflight.js +195 -0
  207. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +801 -0
  208. package/.agents/scripts/lib/bootstrap/prompt.js +480 -0
  209. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +370 -0
  210. package/.agents/scripts/lib/bootstrap/summary.js +75 -0
  211. package/.agents/scripts/lib/bootstrap/workflow-audit.js +256 -0
  212. package/.agents/scripts/lib/branch-name-guard.js +98 -0
  213. package/.agents/scripts/lib/c8-cli-path.js +21 -0
  214. package/.agents/scripts/lib/changed-files.js +184 -0
  215. package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +104 -0
  216. package/.agents/scripts/lib/checks/core-bare-clean.js +48 -0
  217. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +54 -0
  218. package/.agents/scripts/lib/checks/index.js +288 -0
  219. package/.agents/scripts/lib/checks/push-hook-parity.js +106 -0
  220. package/.agents/scripts/lib/checks/stale-origin-epic.js +49 -0
  221. package/.agents/scripts/lib/checks/state.js +558 -0
  222. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +186 -0
  223. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +182 -0
  224. package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +92 -0
  225. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +81 -0
  226. package/.agents/scripts/lib/checks/worktree-residue-biome.js +55 -0
  227. package/.agents/scripts/lib/cli/parse-numeric.js +60 -0
  228. package/.agents/scripts/lib/cli/standard-args.js +351 -0
  229. package/.agents/scripts/lib/cli-args.js +286 -0
  230. package/.agents/scripts/lib/cli-utils.js +69 -0
  231. package/.agents/scripts/lib/close-validation/projections/head-sha.js +44 -0
  232. package/.agents/scripts/lib/close-validation/projections/inputs.js +86 -0
  233. package/.agents/scripts/lib/close-validation/projections/maintainability.js +286 -0
  234. package/.agents/scripts/lib/close-validation.js +897 -0
  235. package/.agents/scripts/lib/codebase-snapshot.js +513 -0
  236. package/.agents/scripts/lib/command-header.js +33 -0
  237. package/.agents/scripts/lib/config/acceptance-eval.js +95 -0
  238. package/.agents/scripts/lib/config/baselines.js +60 -0
  239. package/.agents/scripts/lib/config/ci.js +30 -0
  240. package/.agents/scripts/lib/config/commands.js +36 -0
  241. package/.agents/scripts/lib/config/defaults.js +119 -0
  242. package/.agents/scripts/lib/config/explain.js +348 -0
  243. package/.agents/scripts/lib/config/gates/bundle-size.schema.js +23 -0
  244. package/.agents/scripts/lib/config/gates/coverage.schema.js +18 -0
  245. package/.agents/scripts/lib/config/gates/crap.schema.js +33 -0
  246. package/.agents/scripts/lib/config/gates/duplication.schema.js +26 -0
  247. package/.agents/scripts/lib/config/gates/index.js +36 -0
  248. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +23 -0
  249. package/.agents/scripts/lib/config/gates/lint.schema.js +9 -0
  250. package/.agents/scripts/lib/config/gates/maintainability.schema.js +20 -0
  251. package/.agents/scripts/lib/config/gates/mutation.schema.js +12 -0
  252. package/.agents/scripts/lib/config/gates/shared.js +117 -0
  253. package/.agents/scripts/lib/config/github.js +122 -0
  254. package/.agents/scripts/lib/config/lifecycle.js +40 -0
  255. package/.agents/scripts/lib/config/limits.js +211 -0
  256. package/.agents/scripts/lib/config/paths.js +73 -0
  257. package/.agents/scripts/lib/config/preflight.js +58 -0
  258. package/.agents/scripts/lib/config/quality.js +665 -0
  259. package/.agents/scripts/lib/config/retro.js +77 -0
  260. package/.agents/scripts/lib/config/runners.js +105 -0
  261. package/.agents/scripts/lib/config/runtime.js +167 -0
  262. package/.agents/scripts/lib/config/shared.js +46 -0
  263. package/.agents/scripts/lib/config/sync-agentrc.js +243 -0
  264. package/.agents/scripts/lib/config/temp-paths.js +373 -0
  265. package/.agents/scripts/lib/config/validate-orchestration.js +81 -0
  266. package/.agents/scripts/lib/config/worktree-isolation.js +80 -0
  267. package/.agents/scripts/lib/config-resolver.js +298 -0
  268. package/.agents/scripts/lib/config-schema-shared.js +32 -0
  269. package/.agents/scripts/lib/config-schema.js +20 -0
  270. package/.agents/scripts/lib/config-settings-schema-delivery.js +332 -0
  271. package/.agents/scripts/lib/config-settings-schema-quality.js +165 -0
  272. package/.agents/scripts/lib/config-settings-schema.js +420 -0
  273. package/.agents/scripts/lib/coverage-baseline.js +352 -0
  274. package/.agents/scripts/lib/coverage-capture.js +195 -0
  275. package/.agents/scripts/lib/coverage-utils.js +239 -0
  276. package/.agents/scripts/lib/cpu-pool.js +223 -0
  277. package/.agents/scripts/lib/crap-engine.js +119 -0
  278. package/.agents/scripts/lib/crap-utils.js +479 -0
  279. package/.agents/scripts/lib/degraded-mode.js +69 -0
  280. package/.agents/scripts/lib/dependency-parser.js +129 -0
  281. package/.agents/scripts/lib/duplicate-search.js +189 -0
  282. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +70 -0
  283. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +197 -0
  284. package/.agents/scripts/lib/dynamic-workflow/capability.js +396 -0
  285. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +80 -0
  286. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +72 -0
  287. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +90 -0
  288. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +43 -0
  289. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +83 -0
  290. package/.agents/scripts/lib/env-loader.js +52 -0
  291. package/.agents/scripts/lib/epic-merge-lock.js +239 -0
  292. package/.agents/scripts/lib/epic-plan-clarity.js +142 -0
  293. package/.agents/scripts/lib/epic-plan-ideation.js +228 -0
  294. package/.agents/scripts/lib/error-redactor.js +125 -0
  295. package/.agents/scripts/lib/errors/index.js +67 -0
  296. package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +230 -0
  297. package/.agents/scripts/lib/feedback-loop/code-review-graduator.js +207 -0
  298. package/.agents/scripts/lib/feedback-loop/graduator-core.js +421 -0
  299. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +480 -0
  300. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +229 -0
  301. package/.agents/scripts/lib/findings/classify-finding.js +195 -0
  302. package/.agents/scripts/lib/findings/promote-finding.js +353 -0
  303. package/.agents/scripts/lib/findings/route-finding.js +283 -0
  304. package/.agents/scripts/lib/findings/semantic-issue-search.js +179 -0
  305. package/.agents/scripts/lib/findings/severity.js +102 -0
  306. package/.agents/scripts/lib/gates/baseline-store.js +106 -0
  307. package/.agents/scripts/lib/gates/friction.js +43 -0
  308. package/.agents/scripts/lib/gh-exec.js +553 -0
  309. package/.agents/scripts/lib/git/cached-fetch.js +0 -0
  310. package/.agents/scripts/lib/git/sync-from-base.js +162 -0
  311. package/.agents/scripts/lib/git-branch-cleanup.js +213 -0
  312. package/.agents/scripts/lib/git-branch-lifecycle.js +353 -0
  313. package/.agents/scripts/lib/git-merge-orchestrator.js +261 -0
  314. package/.agents/scripts/lib/git-utils.js +363 -0
  315. package/.agents/scripts/lib/github-url.js +29 -0
  316. package/.agents/scripts/lib/install-cmd-parser.js +51 -0
  317. package/.agents/scripts/lib/issue-link-parser.js +74 -0
  318. package/.agents/scripts/lib/json-utils.js +60 -0
  319. package/.agents/scripts/lib/label-constants.js +169 -0
  320. package/.agents/scripts/lib/label-taxonomy.js +200 -0
  321. package/.agents/scripts/lib/maintainability-engine.js +164 -0
  322. package/.agents/scripts/lib/maintainability-utils.js +343 -0
  323. package/.agents/scripts/lib/mandrel-catalog.js +170 -0
  324. package/.agents/scripts/lib/mutation/baseline-snapshot.js +238 -0
  325. package/.agents/scripts/lib/mutation/config-detector.js +119 -0
  326. package/.agents/scripts/lib/mutation/stryker-runner.js +306 -0
  327. package/.agents/scripts/lib/mutation/survivor-report.js +160 -0
  328. package/.agents/scripts/lib/notifications/notifier.js +75 -0
  329. package/.agents/scripts/lib/observability/active-story-env.js +182 -0
  330. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +221 -0
  331. package/.agents/scripts/lib/observability/perf-aggregator.js +887 -0
  332. package/.agents/scripts/lib/observability/perf-report-readers.js +319 -0
  333. package/.agents/scripts/lib/observability/perf-report-render.js +182 -0
  334. package/.agents/scripts/lib/observability/signals-writer.js +296 -0
  335. package/.agents/scripts/lib/observability/source-classifier.js +103 -0
  336. package/.agents/scripts/lib/observability/tool-trace-hook.js +417 -0
  337. package/.agents/scripts/lib/onboard/detect-stack.js +300 -0
  338. package/.agents/scripts/lib/onboard/scaffold-docs.js +128 -0
  339. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +173 -0
  340. package/.agents/scripts/lib/orchestration/cascade-grouping.js +275 -0
  341. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +131 -0
  342. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +80 -0
  343. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +132 -0
  344. package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +142 -0
  345. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +149 -0
  346. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +158 -0
  347. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +56 -0
  348. package/.agents/scripts/lib/orchestration/code-review.js +652 -0
  349. package/.agents/scripts/lib/orchestration/column-sync.js +286 -0
  350. package/.agents/scripts/lib/orchestration/context-envelope.js +280 -0
  351. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +581 -0
  352. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +88 -0
  353. package/.agents/scripts/lib/orchestration/detectors-phase.js +188 -0
  354. package/.agents/scripts/lib/orchestration/dispatch-engine.js +144 -0
  355. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +206 -0
  356. package/.agents/scripts/lib/orchestration/doc-reader.js +94 -0
  357. package/.agents/scripts/lib/orchestration/epic-cleanup.js +473 -0
  358. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +310 -0
  359. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/cli.js +167 -0
  360. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +151 -0
  361. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +74 -0
  362. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +78 -0
  363. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +72 -0
  364. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +155 -0
  365. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +321 -0
  366. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +75 -0
  367. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +86 -0
  368. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +235 -0
  369. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +197 -0
  370. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +48 -0
  371. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +94 -0
  372. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +414 -0
  373. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +55 -0
  374. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +105 -0
  375. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +235 -0
  376. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +120 -0
  377. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +118 -0
  378. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +295 -0
  379. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +186 -0
  380. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +50 -0
  381. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +146 -0
  382. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +110 -0
  383. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +392 -0
  384. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +217 -0
  385. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +235 -0
  386. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter.js +69 -0
  387. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +32 -0
  388. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +291 -0
  389. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +175 -0
  390. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +37 -0
  391. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +127 -0
  392. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +400 -0
  393. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +285 -0
  394. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +66 -0
  395. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +797 -0
  396. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +619 -0
  397. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +335 -0
  398. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +230 -0
  399. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +363 -0
  400. package/.agents/scripts/lib/orchestration/error-journal.js +139 -0
  401. package/.agents/scripts/lib/orchestration/file-assumption-enum.js +31 -0
  402. package/.agents/scripts/lib/orchestration/file-assumptions.js +506 -0
  403. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +116 -0
  404. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +241 -0
  405. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +489 -0
  406. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +88 -0
  407. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +219 -0
  408. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +309 -0
  409. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +99 -0
  410. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +123 -0
  411. package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +57 -0
  412. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +114 -0
  413. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +426 -0
  414. package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +84 -0
  415. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +365 -0
  416. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +72 -0
  417. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +69 -0
  418. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +214 -0
  419. package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +137 -0
  420. package/.agents/scripts/lib/orchestration/label-transitions.js +43 -0
  421. package/.agents/scripts/lib/orchestration/lifecycle/bus.js +309 -0
  422. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +147 -0
  423. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +155 -0
  424. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +226 -0
  425. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +69 -0
  426. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +378 -0
  427. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +248 -0
  428. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +527 -0
  429. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +259 -0
  430. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +278 -0
  431. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +355 -0
  432. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +647 -0
  433. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +331 -0
  434. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +140 -0
  435. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +421 -0
  436. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +168 -0
  437. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +668 -0
  438. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +322 -0
  439. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +114 -0
  440. package/.agents/scripts/lib/orchestration/manifest-builder.js +216 -0
  441. package/.agents/scripts/lib/orchestration/model-attribution.js +390 -0
  442. package/.agents/scripts/lib/orchestration/parked-follow-ons.js +147 -0
  443. package/.agents/scripts/lib/orchestration/phase-runner.js +87 -0
  444. package/.agents/scripts/lib/orchestration/plan-review-routing.js +63 -0
  445. package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +86 -0
  446. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +212 -0
  447. package/.agents/scripts/lib/orchestration/planning-context-budget.js +213 -0
  448. package/.agents/scripts/lib/orchestration/planning-risk.js +155 -0
  449. package/.agents/scripts/lib/orchestration/planning-state-manager.js +318 -0
  450. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +56 -0
  451. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +33 -0
  452. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +78 -0
  453. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +68 -0
  454. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +118 -0
  455. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +396 -0
  456. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +205 -0
  457. package/.agents/scripts/lib/orchestration/pr-base-guard.js +47 -0
  458. package/.agents/scripts/lib/orchestration/preflight-cache.js +164 -0
  459. package/.agents/scripts/lib/orchestration/reassert-status-column.js +202 -0
  460. package/.agents/scripts/lib/orchestration/reconciler.js +137 -0
  461. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +152 -0
  462. package/.agents/scripts/lib/orchestration/recut.js +56 -0
  463. package/.agents/scripts/lib/orchestration/resolves-token.js +127 -0
  464. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +94 -0
  465. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +448 -0
  466. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +335 -0
  467. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +133 -0
  468. package/.agents/scripts/lib/orchestration/retro-heuristics.js +57 -0
  469. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +275 -0
  470. package/.agents/scripts/lib/orchestration/retro-proposals.js +395 -0
  471. package/.agents/scripts/lib/orchestration/retro-runner.js +171 -0
  472. package/.agents/scripts/lib/orchestration/review-depth.js +93 -0
  473. package/.agents/scripts/lib/orchestration/review-providers/codex.js +363 -0
  474. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +205 -0
  475. package/.agents/scripts/lib/orchestration/review-providers/native.js +805 -0
  476. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +73 -0
  477. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +396 -0
  478. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +373 -0
  479. package/.agents/scripts/lib/orchestration/review-providers/types.js +89 -0
  480. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +107 -0
  481. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +159 -0
  482. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +194 -0
  483. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +81 -0
  484. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +190 -0
  485. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +70 -0
  486. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +106 -0
  487. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +42 -0
  488. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +73 -0
  489. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +225 -0
  490. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +315 -0
  491. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +149 -0
  492. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +110 -0
  493. package/.agents/scripts/lib/orchestration/spec-freshness.js +320 -0
  494. package/.agents/scripts/lib/orchestration/spec-renderer.js +456 -0
  495. package/.agents/scripts/lib/orchestration/spec-section-validator.js +80 -0
  496. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +797 -0
  497. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +163 -0
  498. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +152 -0
  499. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +387 -0
  500. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +266 -0
  501. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +48 -0
  502. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +67 -0
  503. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +161 -0
  504. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +117 -0
  505. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +86 -0
  506. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +147 -0
  507. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +142 -0
  508. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +62 -0
  509. package/.agents/scripts/lib/orchestration/story-close/format-autofix-scoped.js +221 -0
  510. package/.agents/scripts/lib/orchestration/story-close/format-autofix-shared.js +123 -0
  511. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +216 -0
  512. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +636 -0
  513. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +198 -0
  514. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +105 -0
  515. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +222 -0
  516. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +220 -0
  517. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +291 -0
  518. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +234 -0
  519. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +110 -0
  520. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +86 -0
  521. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +112 -0
  522. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +157 -0
  523. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +434 -0
  524. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +290 -0
  525. package/.agents/scripts/lib/orchestration/story-close-recovery.js +643 -0
  526. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +67 -0
  527. package/.agents/scripts/lib/orchestration/task-body-validator.js +391 -0
  528. package/.agents/scripts/lib/orchestration/ticket-lease.js +358 -0
  529. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +783 -0
  530. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +367 -0
  531. package/.agents/scripts/lib/orchestration/ticket-validator.js +691 -0
  532. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +723 -0
  533. package/.agents/scripts/lib/orchestration/ticketing/reads.js +474 -0
  534. package/.agents/scripts/lib/orchestration/ticketing/state.js +559 -0
  535. package/.agents/scripts/lib/orchestration/ticketing.js +55 -0
  536. package/.agents/scripts/lib/orchestration/wave-marker.js +28 -0
  537. package/.agents/scripts/lib/orchestration/wave-record-io.js +277 -0
  538. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +189 -0
  539. package/.agents/scripts/lib/orchestration/wave-record-projection.js +423 -0
  540. package/.agents/scripts/lib/path-security.js +25 -0
  541. package/.agents/scripts/lib/plan-phase-cleanup.js +125 -0
  542. package/.agents/scripts/lib/preflight-runner.js +196 -0
  543. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +95 -0
  544. package/.agents/scripts/lib/presentation/manifest-builder.js +245 -0
  545. package/.agents/scripts/lib/presentation/manifest-formatter.js +243 -0
  546. package/.agents/scripts/lib/presentation/manifest-helpers.js +213 -0
  547. package/.agents/scripts/lib/presentation/manifest-persistence.js +262 -0
  548. package/.agents/scripts/lib/presentation/manifest-procedures.js +55 -0
  549. package/.agents/scripts/lib/presentation/manifest-render-waves.js +252 -0
  550. package/.agents/scripts/lib/presentation/manifest-renderer.js +188 -0
  551. package/.agents/scripts/lib/presentation/manifest-story-views.js +119 -0
  552. package/.agents/scripts/lib/provider-factory.js +80 -0
  553. package/.agents/scripts/lib/push-epic-retry.js +209 -0
  554. package/.agents/scripts/lib/qa/console-allowlist.js +151 -0
  555. package/.agents/scripts/lib/qa/coverage-report.js +181 -0
  556. package/.agents/scripts/lib/qa/coverage-verdict.js +296 -0
  557. package/.agents/scripts/lib/qa/propose-missing-test.js +95 -0
  558. package/.agents/scripts/lib/qa/qa-context-hydrator.js +296 -0
  559. package/.agents/scripts/lib/qa/qa-session.js +197 -0
  560. package/.agents/scripts/lib/qa/redact-evidence.js +245 -0
  561. package/.agents/scripts/lib/qa/resolve-qa-contract.js +190 -0
  562. package/.agents/scripts/lib/qa/resolve-selection.js +373 -0
  563. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +100 -0
  564. package/.agents/scripts/lib/runtime-deps/manifest.js +96 -0
  565. package/.agents/scripts/lib/runtime-deps/preflight.js +78 -0
  566. package/.agents/scripts/lib/runtime-deps/scan-imports.js +202 -0
  567. package/.agents/scripts/lib/signals/detectors/common.js +36 -0
  568. package/.agents/scripts/lib/signals/detectors/hotspot.js +298 -0
  569. package/.agents/scripts/lib/signals/detectors/index.js +14 -0
  570. package/.agents/scripts/lib/signals/detectors/retry.js +289 -0
  571. package/.agents/scripts/lib/signals/detectors/rework.js +204 -0
  572. package/.agents/scripts/lib/signals/index.js +39 -0
  573. package/.agents/scripts/lib/signals/read.js +268 -0
  574. package/.agents/scripts/lib/signals/schema.js +225 -0
  575. package/.agents/scripts/lib/signals/span-tree.js +290 -0
  576. package/.agents/scripts/lib/signals/write.js +19 -0
  577. package/.agents/scripts/lib/single-story/confirm-merge.js +201 -0
  578. package/.agents/scripts/lib/single-story/story-merged-notify.js +126 -0
  579. package/.agents/scripts/lib/single-story-sweep/protection.js +274 -0
  580. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +169 -0
  581. package/.agents/scripts/lib/single-story-sweep.js +329 -0
  582. package/.agents/scripts/lib/skills/parse-skill.js +202 -0
  583. package/.agents/scripts/lib/skills/walk-skill-files.js +56 -0
  584. package/.agents/scripts/lib/spec/index.js +36 -0
  585. package/.agents/scripts/lib/spec/loader.js +425 -0
  586. package/.agents/scripts/lib/spec/state.js +217 -0
  587. package/.agents/scripts/lib/story-body/story-body.js +743 -0
  588. package/.agents/scripts/lib/story-init/blocker-validator.js +68 -0
  589. package/.agents/scripts/lib/story-init/branch-initializer.js +422 -0
  590. package/.agents/scripts/lib/story-init/context-resolver.js +92 -0
  591. package/.agents/scripts/lib/story-init/donor-precheck.js +207 -0
  592. package/.agents/scripts/lib/story-init/hierarchy-tracer.js +36 -0
  593. package/.agents/scripts/lib/story-init/state-transitioner.js +80 -0
  594. package/.agents/scripts/lib/story-init/task-graph-builder.js +114 -0
  595. package/.agents/scripts/lib/story-init/transition-summary.js +34 -0
  596. package/.agents/scripts/lib/story-lifecycle.js +186 -0
  597. package/.agents/scripts/lib/story-plan.js +246 -0
  598. package/.agents/scripts/lib/task-utils.js +26 -0
  599. package/.agents/scripts/lib/templates/decomposer-prompts.js +168 -0
  600. package/.agents/scripts/lib/test-env.js +30 -0
  601. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +52 -0
  602. package/.agents/scripts/lib/test-isolate/list-files.js +90 -0
  603. package/.agents/scripts/lib/test-isolate/parse-tap.js +75 -0
  604. package/.agents/scripts/lib/test-isolate/runner.js +483 -0
  605. package/.agents/scripts/lib/test-profile/parse-tap.js +136 -0
  606. package/.agents/scripts/lib/test-profile/render-report.js +45 -0
  607. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +35 -0
  608. package/.agents/scripts/lib/test-tiers.js +94 -0
  609. package/.agents/scripts/lib/util/concurrent-map.js +59 -0
  610. package/.agents/scripts/lib/util/phase-timer-state.js +72 -0
  611. package/.agents/scripts/lib/util/phase-timer.js +163 -0
  612. package/.agents/scripts/lib/util/poll-loop.js +86 -0
  613. package/.agents/scripts/lib/util/with-timeout.js +32 -0
  614. package/.agents/scripts/lib/validation-evidence.js +323 -0
  615. package/.agents/scripts/lib/wave-runner/tick.js +665 -0
  616. package/.agents/scripts/lib/wave-runner/wave-checkpoint.js +91 -0
  617. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +19 -0
  618. package/.agents/scripts/lib/workers/crap-worker.js +197 -0
  619. package/.agents/scripts/lib/workers/maintainability-report-worker.js +137 -0
  620. package/.agents/scripts/lib/workers/maintainability-worker.js +79 -0
  621. package/.agents/scripts/lib/workspace-provisioner.js +189 -0
  622. package/.agents/scripts/lib/worktree/bootstrapper.js +48 -0
  623. package/.agents/scripts/lib/worktree/inspector.js +140 -0
  624. package/.agents/scripts/lib/worktree/lifecycle/creation.js +118 -0
  625. package/.agents/scripts/lib/worktree/lifecycle/drift-detection.js +62 -0
  626. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +276 -0
  627. package/.agents/scripts/lib/worktree/lifecycle/gc.js +49 -0
  628. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +178 -0
  629. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +264 -0
  630. package/.agents/scripts/lib/worktree/lifecycle/precheck.js +100 -0
  631. package/.agents/scripts/lib/worktree/lifecycle/reap.js +588 -0
  632. package/.agents/scripts/lib/worktree/lifecycle/registry-sync.js +124 -0
  633. package/.agents/scripts/lib/worktree/lifecycle/shared.js +26 -0
  634. package/.agents/scripts/lib/worktree/lifecycle-manager.js +40 -0
  635. package/.agents/scripts/lib/worktree/node-modules-strategy.js +349 -0
  636. package/.agents/scripts/lib/worktree-manager.js +243 -0
  637. package/.agents/scripts/lifecycle-diff.js +206 -0
  638. package/.agents/scripts/lifecycle-emit-story-dispatch.js +194 -0
  639. package/.agents/scripts/lifecycle-emit.js +479 -0
  640. package/.agents/scripts/lint-baseline.js +507 -0
  641. package/.agents/scripts/lint-label-vocabulary.js +237 -0
  642. package/.agents/scripts/loc-delta.js +205 -0
  643. package/.agents/scripts/notify.js +307 -0
  644. package/.agents/scripts/package.json +3 -0
  645. package/.agents/scripts/post-structured-comment.js +127 -0
  646. package/.agents/scripts/pr-watch-with-update.js +152 -0
  647. package/.agents/scripts/providers/github/auth.js +65 -0
  648. package/.agents/scripts/providers/github/board-add.js +63 -0
  649. package/.agents/scripts/providers/github/branch-protection.js +186 -0
  650. package/.agents/scripts/providers/github/cache.js +72 -0
  651. package/.agents/scripts/providers/github/comments.js +131 -0
  652. package/.agents/scripts/providers/github/compose.js +111 -0
  653. package/.agents/scripts/providers/github/errors.js +242 -0
  654. package/.agents/scripts/providers/github/issues.js +242 -0
  655. package/.agents/scripts/providers/github/labels.js +179 -0
  656. package/.agents/scripts/providers/github/mappers.js +126 -0
  657. package/.agents/scripts/providers/github/merge-methods.js +82 -0
  658. package/.agents/scripts/providers/github/project-board.js +47 -0
  659. package/.agents/scripts/providers/github/projects-v2-graphql.js +472 -0
  660. package/.agents/scripts/providers/github/prs.js +103 -0
  661. package/.agents/scripts/providers/github/request-helpers.js +110 -0
  662. package/.agents/scripts/providers/github/sub-issues.js +369 -0
  663. package/.agents/scripts/providers/github/tickets.js +381 -0
  664. package/.agents/scripts/providers/github/transient-retry.js +62 -0
  665. package/.agents/scripts/providers/github.js +157 -0
  666. package/.agents/scripts/quality-preview.js +327 -0
  667. package/.agents/scripts/quality-watch.js +223 -0
  668. package/.agents/scripts/render-manifest.js +143 -0
  669. package/.agents/scripts/resync-status-column.js +176 -0
  670. package/.agents/scripts/retro-run.js +167 -0
  671. package/.agents/scripts/run-audit-suite.js +97 -0
  672. package/.agents/scripts/run-coverage.js +103 -0
  673. package/.agents/scripts/run-lint.js +94 -0
  674. package/.agents/scripts/run-test-profile.js +126 -0
  675. package/.agents/scripts/run-tests.js +185 -0
  676. package/.agents/scripts/run-verify.js +56 -0
  677. package/.agents/scripts/select-audits.js +155 -0
  678. package/.agents/scripts/signals-view.js +294 -0
  679. package/.agents/scripts/single-story-close.js +83 -0
  680. package/.agents/scripts/single-story-confirm-merge.js +183 -0
  681. package/.agents/scripts/single-story-init.js +692 -0
  682. package/.agents/scripts/stories-wave-tick.js +415 -0
  683. package/.agents/scripts/story-close.js +246 -0
  684. package/.agents/scripts/story-deliver-prepare.js +267 -0
  685. package/.agents/scripts/story-init.js +516 -0
  686. package/.agents/scripts/story-phase.js +327 -0
  687. package/.agents/scripts/story-plan.js +284 -0
  688. package/.agents/scripts/sync-agentrc.js +71 -0
  689. package/.agents/scripts/sync-branch-from-base.js +138 -0
  690. package/.agents/scripts/sync-claude-commands.js +151 -0
  691. package/.agents/scripts/test-isolate.js +222 -0
  692. package/.agents/scripts/test-wrapper.js +108 -0
  693. package/.agents/scripts/update-coverage-baseline.js +129 -0
  694. package/.agents/scripts/update-crap-baseline.js +177 -0
  695. package/.agents/scripts/update-duplication-baseline.js +134 -0
  696. package/.agents/scripts/update-maintainability-baseline.js +183 -0
  697. package/.agents/scripts/update-mutation-baseline.js +189 -0
  698. package/.agents/scripts/update-ticket-state.js +107 -0
  699. package/.agents/scripts/validate-docs-freshness.js +259 -0
  700. package/.agents/scripts/validate-skills.js +278 -0
  701. package/.agents/scripts/wave-tick.js +335 -0
  702. package/.agents/skills/core/analyze-execution/SKILL.md +98 -0
  703. package/.agents/skills/core/api-and-interface-design/SKILL.md +327 -0
  704. package/.agents/skills/core/baseline-refresh/SKILL.md +181 -0
  705. package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +352 -0
  706. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +274 -0
  707. package/.agents/skills/core/ci-cd-and-automation/examples.md +211 -0
  708. package/.agents/skills/core/code-review-and-quality/SKILL.md +421 -0
  709. package/.agents/skills/core/code-simplification/SKILL.md +389 -0
  710. package/.agents/skills/core/context-engineering/SKILL.md +309 -0
  711. package/.agents/skills/core/context-engineering/examples.md +58 -0
  712. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +338 -0
  713. package/.agents/skills/core/deprecation-and-migration/SKILL.md +250 -0
  714. package/.agents/skills/core/diagnose-friction/SKILL.md +79 -0
  715. package/.agents/skills/core/documentation-and-adrs/SKILL.md +323 -0
  716. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +145 -0
  717. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +425 -0
  718. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +393 -0
  719. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +357 -0
  720. package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +352 -0
  721. package/.agents/skills/core/hydrate-context/SKILL.md +118 -0
  722. package/.agents/skills/core/idea-refinement/SKILL.md +317 -0
  723. package/.agents/skills/core/idea-refinement/examples.md +437 -0
  724. package/.agents/skills/core/idea-refinement/frameworks.md +135 -0
  725. package/.agents/skills/core/idea-refinement/refinement-criteria.md +155 -0
  726. package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +15 -0
  727. package/.agents/skills/core/incremental-implementation/SKILL.md +271 -0
  728. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +213 -0
  729. package/.agents/skills/core/knowledge-transfer/SKILL.md +175 -0
  730. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +117 -0
  731. package/.agents/skills/core/performance-optimization/SKILL.md +314 -0
  732. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +277 -0
  733. package/.agents/skills/core/property-based-testing/SKILL.md +148 -0
  734. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +105 -0
  735. package/.agents/skills/core/refactoring-discipline/SKILL.md +111 -0
  736. package/.agents/skills/core/scope-triage/SKILL.md +127 -0
  737. package/.agents/skills/core/security-and-hardening/SKILL.md +400 -0
  738. package/.agents/skills/core/shipping-and-launch/SKILL.md +328 -0
  739. package/.agents/skills/core/spec-driven-development/SKILL.md +252 -0
  740. package/.agents/skills/core/test-driven-development/SKILL.md +475 -0
  741. package/.agents/skills/core/using-agent-skills/SKILL.md +232 -0
  742. package/.agents/skills/skills.index.json +596 -0
  743. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +31 -0
  744. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +51 -0
  745. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +48 -0
  746. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +31 -0
  747. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +33 -0
  748. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +31 -0
  749. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +51 -0
  750. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +54 -0
  751. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +29 -0
  752. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +30 -0
  753. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +57 -0
  754. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +9 -0
  755. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +48 -0
  756. package/.agents/skills/stack/frontend/astro/SKILL.md +62 -0
  757. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +30 -0
  758. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +29 -0
  759. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +50 -0
  760. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +58 -0
  761. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +34 -0
  762. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +51 -0
  763. package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +257 -0
  764. package/.agents/skills/stack/qa/gherkin-authoring/examples/invoice-issue.feature +41 -0
  765. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +199 -0
  766. package/.agents/skills/stack/qa/playwright/SKILL.md +50 -0
  767. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +188 -0
  768. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +142 -0
  769. package/.agents/skills/stack/qa/qa-harness/SKILL.md +220 -0
  770. package/.agents/skills/stack/qa/vitest/SKILL.md +51 -0
  771. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +68 -0
  772. package/.agents/starter-agentrc.json +22 -0
  773. package/.agents/templates/agent-protocol.md +72 -0
  774. package/.agents/templates/docs/architecture.md +30 -0
  775. package/.agents/templates/docs/decisions.md +24 -0
  776. package/.agents/templates/epic-from-idea.md +21 -0
  777. package/.agents/templates/single-story-body.md +17 -0
  778. package/.agents/workflows/agents-update.md +415 -0
  779. package/.agents/workflows/audit-architecture.md +312 -0
  780. package/.agents/workflows/audit-clean-code.md +179 -0
  781. package/.agents/workflows/audit-dependencies.md +91 -0
  782. package/.agents/workflows/audit-devops.md +110 -0
  783. package/.agents/workflows/audit-lighthouse.md +260 -0
  784. package/.agents/workflows/audit-performance.md +161 -0
  785. package/.agents/workflows/audit-privacy.md +104 -0
  786. package/.agents/workflows/audit-quality.md +191 -0
  787. package/.agents/workflows/audit-security.md +156 -0
  788. package/.agents/workflows/audit-seo.md +118 -0
  789. package/.agents/workflows/audit-sre.md +139 -0
  790. package/.agents/workflows/audit-to-stories.md +257 -0
  791. package/.agents/workflows/audit-ux-ui.md +102 -0
  792. package/.agents/workflows/epic-deliver.md +864 -0
  793. package/.agents/workflows/epic-plan.md +998 -0
  794. package/.agents/workflows/explain.md +118 -0
  795. package/.agents/workflows/git-cleanup.md +250 -0
  796. package/.agents/workflows/git-commit-all.md +15 -0
  797. package/.agents/workflows/git-merge-pr.md +377 -0
  798. package/.agents/workflows/git-pr-all.md +278 -0
  799. package/.agents/workflows/git-push.md +60 -0
  800. package/.agents/workflows/helpers/_merge-conflict-template.md +54 -0
  801. package/.agents/workflows/helpers/acceptance-self-eval.md +74 -0
  802. package/.agents/workflows/helpers/agents-sync-config.md +129 -0
  803. package/.agents/workflows/helpers/code-quality-guardrails.md +101 -0
  804. package/.agents/workflows/helpers/code-review.md +370 -0
  805. package/.agents/workflows/helpers/diagnose.md +117 -0
  806. package/.agents/workflows/helpers/epic-audit.md +295 -0
  807. package/.agents/workflows/helpers/epic-deliver-story.md +370 -0
  808. package/.agents/workflows/helpers/epic-plan-decompose.md +199 -0
  809. package/.agents/workflows/helpers/epic-plan-spec.md +184 -0
  810. package/.agents/workflows/helpers/epic-testing.md +125 -0
  811. package/.agents/workflows/helpers/parallel-tooling.md +88 -0
  812. package/.agents/workflows/helpers/signals.md +112 -0
  813. package/.agents/workflows/helpers/single-story-deliver.md +636 -0
  814. package/.agents/workflows/helpers/worktree-lifecycle.md +317 -0
  815. package/.agents/workflows/onboard.md +207 -0
  816. package/.agents/workflows/qa-assist.md +293 -0
  817. package/.agents/workflows/qa-explore.md +350 -0
  818. package/.agents/workflows/qa-run-harness.md +288 -0
  819. package/.agents/workflows/story-deliver.md +327 -0
  820. package/.agents/workflows/story-plan.md +233 -0
  821. package/LICENSE +21 -0
  822. package/README.md +193 -0
  823. package/bin/mandrel.js +56 -0
  824. package/bin/postinstall.js +195 -0
  825. package/lib/cli/__tests__/migrate.test.js +268 -0
  826. package/lib/cli/__tests__/sync-local-zone.test.js +247 -0
  827. package/lib/cli/__tests__/sync.test.js +372 -0
  828. package/lib/cli/__tests__/update-major.test.js +217 -0
  829. package/lib/cli/__tests__/update.test.js +696 -0
  830. package/lib/cli/__tests__/version-check.test.js +398 -0
  831. package/lib/cli/doctor.js +124 -0
  832. package/lib/cli/explain.js +107 -0
  833. package/lib/cli/migrate.js +260 -0
  834. package/lib/cli/registry.js +830 -0
  835. package/lib/cli/sync-commands.js +50 -0
  836. package/lib/cli/sync.js +200 -0
  837. package/lib/cli/uninstall.js +795 -0
  838. package/lib/cli/update.js +854 -0
  839. package/lib/cli/version-check.js +206 -0
  840. package/lib/migrations/README.md +69 -0
  841. package/lib/migrations/__tests__/index.test.js +216 -0
  842. package/lib/migrations/index.js +164 -0
  843. package/package.json +105 -0
@@ -0,0 +1,854 @@
1
+ // lib/cli/update.js
2
+ /**
3
+ * `mandrel update` subcommand — the auto-update orchestrator (f-update-command,
4
+ * Story #3503, Epic #3437 — Auto-Update & Version Lifecycle).
5
+ *
6
+ * Advances `mandrel` to the newest **non-major** published version,
7
+ * re-materializes `.agents/`, runs applicable version-keyed migrations,
8
+ * surfaces the target changelog, and verifies the result via the doctor
9
+ * registry. A **major** crossing (e.g. `1.x → 2.0`) is gated: the orchestrator
10
+ * refuses to apply it without `--major`, prints a pointer to
11
+ * `docs/upgrade-major.md`, and exits non-zero without touching anything.
12
+ *
13
+ * ## Ordered cycle (happy path, non-major bump)
14
+ *
15
+ * 1. resolve target version (newest published) and the current version
16
+ * 2. **major gate** — decline + non-zero exit when the target crosses a
17
+ * major boundary and `--major` is absent
18
+ * 3. no-op short-circuit — already on the newest version ⇒ nothing to do
19
+ * 4. install — bump the dependency (lockfile bump left STAGED).
20
+ * The package manager is auto-detected from the lockfile in the project
21
+ * root: `pnpm-lock.yaml` ⇒ `pnpm add -D …` (with `-w` at a
22
+ * `pnpm-workspace.yaml` root), `yarn.lock` ⇒ `yarn add -D …`, otherwise
23
+ * `npm install …`. An explicit `--install-cmd "<pm> <args>"` overrides
24
+ * detection; a `{target}` placeholder in the override is substituted with
25
+ * the resolved version so an override can still consume the auto-probed
26
+ * newest. The registry probe in step 1 always stays on `npm view` (a
27
+ * PM-agnostic registry query).
28
+ * 5. runSync — re-materialize ./.agents/ from the new payload
29
+ * 6. runMigrations — apply version-keyed steps for the crossed range
30
+ * 7. doctor — run the check registry; success ⇒ all checks pass
31
+ * 8. surface the changelog for the target version
32
+ *
33
+ * ## No git mutation
34
+ *
35
+ * The npm dependency bump rewrites `package.json` / `package-lock.json` in the
36
+ * working tree but the orchestrator performs **no** `git add` / `git commit`:
37
+ * the lockfile bump is left staged-on-disk for the operator to review and
38
+ * commit. This module never shells out to git.
39
+ *
40
+ * ## `--dry-run`
41
+ *
42
+ * Prints the resolved target version and the ordered step plan, then returns
43
+ * without invoking any effectful seam (no npm update, no sync, no migrations,
44
+ * no doctor) and writing nothing.
45
+ *
46
+ * ## Major gate
47
+ *
48
+ * The project sits on the **1.x** line under release-please
49
+ * `always-bump-minor` ([AGENTS.md § Major-version policy]); a major release is
50
+ * a deliberate manual operator decision, so adopting one must be equally
51
+ * deliberate. When the newest version's major exceeds the current major:
52
+ * - **without `--major`**: print the available version + the
53
+ * `docs/upgrade-major.md` runbook pointer, exit non-zero, and invoke
54
+ * **no** npm-update / sync / migration / doctor seam.
55
+ * - **with `--major`**: apply the major target and print the runbook inline.
56
+ * Routine minor/patch bumps within the 1.x line are never gated.
57
+ *
58
+ * ## Injectable seams (used by lib/cli/__tests__/update*.test.js)
59
+ *
60
+ * - `argv` — subcommand args (after `mandrel update`)
61
+ * - `currentVersion` — the installed `mandrel` version string
62
+ * - `resolveTargetVersion`— async, returns the newest published version
63
+ * - `npmUpdate` — async, performs the dependency bump (no git);
64
+ * receives `(target, { installCmd })`
65
+ * - `runSync` — re-materializes ./.agents/ (lib/cli/sync.js)
66
+ * - `runMigrations` — version-keyed migration runner (lib/migrations)
67
+ * - `runDoctor` — async, returns { ok, results } from the registry
68
+ * - `surfaceChangelog` — emits the target changelog section
69
+ * - `write` / `writeErr` — stdout / stderr sinks
70
+ * - `exit` — process.exit replacement
71
+ *
72
+ * Security (security-baseline § 5 — Data Leakage & Logging): logs only version
73
+ * strings, step names, and the runbook path. No tokens, credentials, or env
74
+ * values are read or logged; no shell-string interpolation occurs here (the
75
+ * npm bump is delegated to the injected `npmUpdate` seam, which owns transport).
76
+ *
77
+ * ## Windows spawn (CVE-2024-27980)
78
+ *
79
+ * Both child-process boundaries — the `npm view` registry probe and the
80
+ * install — route through helpers that pass `shell: process.platform ===
81
+ * 'win32'`. On Windows `npm`/`pnpm`/`yarn` resolve to `.cmd` shims, and
82
+ * Node 18.20+/20.12+/22+/24 refuses to spawn `.cmd`/`.bat` with `shell:false`
83
+ * (the CVE-2024-27980 hardening), throwing `spawnSync npm ENOENT`. The win32
84
+ * shell flag is the documented fix. It is injection-safe because every argv
85
+ * here is a **fixed vector**: the probe argv is the constant package name, and
86
+ * the install argv is a tokenized list whose only variable segment is a
87
+ * resolved semver string — see `lib/install-cmd-parser.js` for the shared
88
+ * tokenize-and-spawn rationale this module reuses (no duplicated workaround).
89
+ */
90
+
91
+ import { spawnSync } from 'node:child_process';
92
+ import nodeFs from 'node:fs';
93
+ import path from 'node:path';
94
+ import { fileURLToPath } from 'node:url';
95
+
96
+ import { runInstallCommand } from '../../.agents/scripts/lib/install-cmd-parser.js';
97
+ import { runMigrations as defaultRunMigrations } from '../migrations/index.js';
98
+ import { registry } from './registry.js';
99
+ import { runSync as defaultRunSync } from './sync.js';
100
+ import { isStale } from './version-check.js';
101
+
102
+ /** Path (relative to project root) of the major-upgrade runbook. */
103
+ const RUNBOOK_PATH = 'docs/upgrade-major.md';
104
+
105
+ /** The published package whose newest version `mandrel update` advances to. */
106
+ const PACKAGE_NAME = 'mandrel';
107
+
108
+ /** Default freshness-cache filename — mirrors version-check.js. */
109
+ const DEFAULT_CACHE_FILENAME = 'version-check.json';
110
+
111
+ /**
112
+ * Parse a dotted semver-ish string into a numeric tuple. Non-numeric or
113
+ * missing segments coerce to 0 so a partial version still compares sanely.
114
+ *
115
+ * @param {string} version
116
+ * @returns {[number, number, number]}
117
+ */
118
+ function parseVersion(version) {
119
+ const [major, minor, patch] = String(version).split('.');
120
+ return [
121
+ Number.parseInt(major, 10) || 0,
122
+ Number.parseInt(minor, 10) || 0,
123
+ Number.parseInt(patch, 10) || 0,
124
+ ];
125
+ }
126
+
127
+ /**
128
+ * Compare two version strings. Negative when `a < b`, zero when equal,
129
+ * positive when `a > b` (the standard `Array.sort` comparator contract).
130
+ *
131
+ * @param {string} a
132
+ * @param {string} b
133
+ * @returns {number}
134
+ */
135
+ function compareVersions(a, b) {
136
+ const pa = parseVersion(a);
137
+ const pb = parseVersion(b);
138
+ for (let i = 0; i < 3; i += 1) {
139
+ if (pa[i] !== pb[i]) return pa[i] - pb[i];
140
+ }
141
+ return 0;
142
+ }
143
+
144
+ /**
145
+ * True when `target`'s major axis is strictly greater than `current`'s — the
146
+ * gated "crosses a major boundary" condition.
147
+ *
148
+ * @param {string} current
149
+ * @param {string} target
150
+ * @returns {boolean}
151
+ */
152
+ function crossesMajor(current, target) {
153
+ return parseVersion(target)[0] > parseVersion(current)[0];
154
+ }
155
+
156
+ /**
157
+ * Resolve the installed `mandrel` version from this package's own
158
+ * `package.json`. The module lives at `<root>/lib/cli/update.js`, so the
159
+ * manifest is two directories up.
160
+ *
161
+ * @param {typeof nodeFs} [fs]
162
+ * @returns {string}
163
+ */
164
+ function defaultCurrentVersion(fs = nodeFs) {
165
+ const here = path.dirname(fileURLToPath(import.meta.url));
166
+ const manifestPath = path.resolve(here, '..', '..', 'package.json');
167
+ const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
168
+ return String(parsed.version);
169
+ }
170
+
171
+ /**
172
+ * Resolve the project root — the directory two levels up from this module
173
+ * (`<root>/lib/cli/update.js`). Mirrors `lib/cli/registry.js#resolveProjectRoot`.
174
+ *
175
+ * @returns {string}
176
+ */
177
+ function resolveProjectRoot() {
178
+ const here = path.dirname(fileURLToPath(import.meta.url));
179
+ return path.resolve(here, '..', '..');
180
+ }
181
+
182
+ /**
183
+ * Default `resolveTargetVersion` seam: determine the newest published
184
+ * `mandrel` version via the daily freshness cache (`version-check.js`).
185
+ *
186
+ * This delegates to `isStale`, which honours the 24h-cache semantics: a fresh
187
+ * cache returns the cached version with **zero** network I/O, while a missing,
188
+ * corrupt, or stale cache triggers exactly one network probe (`npm view
189
+ * mandrel version`) and refreshes `temp/version-check.json`. Wiring the
190
+ * production update path through `isStale` is precisely what populates that
191
+ * daily cache, which the `version-current` doctor advisory reads.
192
+ *
193
+ * The network probe shells `npm view` through `spawnSync` with a fixed argument
194
+ * vector (no shell-string interpolation; the package name is a constant). On
195
+ * Windows the spawn sets `shell: true` so the `npm.cmd` shim resolves under the
196
+ * CVE-2024-27980 hardening (mirrors `lib/install-cmd-parser.js`); the fixed
197
+ * argv carries no injection risk even with the shell flag set
198
+ * (security-baseline § Output & Rendering).
199
+ *
200
+ * @param {{
201
+ * cachePath?: string,
202
+ * fs?: typeof nodeFs,
203
+ * runner?: () => string,
204
+ * now?: Date,
205
+ * log?: (msg: string) => void,
206
+ * }} [opts]
207
+ * @returns {Promise<string>} The newest published version string.
208
+ */
209
+ async function defaultResolveTargetVersion({
210
+ cachePath = path.join(resolveProjectRoot(), 'temp', DEFAULT_CACHE_FILENAME),
211
+ fs = nodeFs,
212
+ runner = defaultVersionRunner,
213
+ now = new Date(),
214
+ log = () => {},
215
+ } = {}) {
216
+ const result = await isStale({ cachePath, now, runner, fs, log });
217
+ return String(result.latestVersion);
218
+ }
219
+
220
+ /**
221
+ * Default network `runner` for the freshness probe: shells
222
+ * `npm view mandrel version` synchronously and returns the trimmed
223
+ * stdout. Fixed argv (the package name is a constant), and `shell:true` only on
224
+ * Windows so the `npm.cmd` shim resolves under CVE-2024-27980 — the fixed
225
+ * vector keeps it injection-safe with or without the shell flag.
226
+ *
227
+ * @param {{ spawnSync?: typeof spawnSync }} [deps] — test seam for the spawn
228
+ * boundary; defaults to the real `node:child_process` spawnSync.
229
+ * @returns {string} The newest published version string.
230
+ */
231
+ export function defaultVersionRunner({ spawnSync: spawn = spawnSync } = {}) {
232
+ const r = spawn('npm', ['view', PACKAGE_NAME, 'version'], {
233
+ encoding: 'utf8',
234
+ shell: process.platform === 'win32',
235
+ });
236
+ if (r.error) {
237
+ throw new Error(
238
+ `mandrel update: failed to probe newest ${PACKAGE_NAME} version: ${r.error.message}`,
239
+ );
240
+ }
241
+ if (r.status !== 0) {
242
+ const snippet = (r.stderr || r.stdout || '').trim().slice(0, 200);
243
+ throw new Error(
244
+ `mandrel update: \`npm view ${PACKAGE_NAME} version\` exited ${r.status}: ${snippet}`,
245
+ );
246
+ }
247
+ const version = String(r.stdout || '').trim();
248
+ if (!version) {
249
+ throw new Error(
250
+ `mandrel update: \`npm view ${PACKAGE_NAME} version\` returned no version`,
251
+ );
252
+ }
253
+ return version;
254
+ }
255
+
256
+ /**
257
+ * Map a detected package manager to the command that re-runs a full install.
258
+ * Surfaced in the repair hint when an install fails so the operator can restore
259
+ * `node_modules` to a consistent state (Story #3575 AC-4).
260
+ *
261
+ * @param {'pnpm' | 'yarn' | 'npm'} packageManager
262
+ * @returns {string}
263
+ */
264
+ function repairInstallCommand(packageManager) {
265
+ if (packageManager === 'pnpm') return 'pnpm install';
266
+ if (packageManager === 'yarn') return 'yarn install';
267
+ return 'npm install';
268
+ }
269
+
270
+ /**
271
+ * Detect the project's package manager by probing for a lockfile in `cwd`.
272
+ * Precedence mirrors the ecosystem norm: a `pnpm-lock.yaml` wins over a
273
+ * `yarn.lock`, which wins over the npm default. `workspaceRoot` is true only
274
+ * for pnpm when a `pnpm-workspace.yaml` sits alongside the lockfile — the
275
+ * signal that `pnpm add` must carry `-w` to target the workspace-root manifest.
276
+ *
277
+ * Running the wrong package manager (e.g. `npm install` in a pnpm workspace) is
278
+ * the root cause this resolves (Story #3575): npm chokes on the pnpm-managed
279
+ * tree, exits non-zero, and can flip `node_modules` to a stale store entry.
280
+ * Detecting the lockfile keeps the bump on the operator's real package manager
281
+ * so the change lands in the matching lockfile.
282
+ *
283
+ * @param {string} [cwd] - Project root to probe (default `process.cwd()`).
284
+ * @param {typeof nodeFs} [fs]
285
+ * @returns {{ packageManager: 'pnpm' | 'yarn' | 'npm', workspaceRoot: boolean }}
286
+ */
287
+ export function detectPackageManager(cwd = process.cwd(), fs = nodeFs) {
288
+ const has = (file) => {
289
+ try {
290
+ return fs.existsSync(path.join(cwd, file));
291
+ } catch {
292
+ return false;
293
+ }
294
+ };
295
+ if (has('pnpm-lock.yaml')) {
296
+ return {
297
+ packageManager: 'pnpm',
298
+ workspaceRoot: has('pnpm-workspace.yaml'),
299
+ };
300
+ }
301
+ if (has('yarn.lock')) {
302
+ return { packageManager: 'yarn', workspaceRoot: false };
303
+ }
304
+ return { packageManager: 'npm', workspaceRoot: false };
305
+ }
306
+
307
+ /**
308
+ * Resolve the install command string `defaultNpmUpdate` runs.
309
+ *
310
+ * With no override the command is built from the detected package manager:
311
+ * - `pnpm` ⇒ `pnpm add -D mandrel@<target>` (plus ` -w` at a pnpm
312
+ * workspace root)
313
+ * - `yarn` ⇒ `yarn add -D mandrel@<target>`
314
+ * - `npm` ⇒ `npm install mandrel@<target>` (the unchanged default)
315
+ *
316
+ * An explicit `--install-cmd` override is used verbatim, except that a
317
+ * `{target}` placeholder is substituted with the resolved semver so an override
318
+ * can still consume the auto-probed newest version (Story #3575 AC-3).
319
+ *
320
+ * This function is pure: package-manager detection happens in
321
+ * `detectPackageManager` (the only filesystem seam) and is passed in as
322
+ * `detected`, keeping the command-string assembly trivially unit-testable.
323
+ *
324
+ * @param {string} target - The resolved semver to install.
325
+ * @param {string} [override] - Operator-supplied `--install-cmd` value.
326
+ * @param {{
327
+ * packageManager?: 'pnpm' | 'yarn' | 'npm',
328
+ * workspaceRoot?: boolean,
329
+ * }} [detected]
330
+ * @returns {string}
331
+ */
332
+ export function resolveInstallCmd(
333
+ target,
334
+ override,
335
+ { packageManager = 'npm', workspaceRoot = false } = {},
336
+ ) {
337
+ const trimmed = String(override ?? '').trim();
338
+ if (trimmed.length > 0) {
339
+ return trimmed.includes('{target}')
340
+ ? trimmed.replaceAll('{target}', target)
341
+ : trimmed;
342
+ }
343
+ if (packageManager === 'pnpm') {
344
+ return `pnpm add -D ${PACKAGE_NAME}@${target}${workspaceRoot ? ' -w' : ''}`;
345
+ }
346
+ if (packageManager === 'yarn') {
347
+ return `yarn add -D ${PACKAGE_NAME}@${target}`;
348
+ }
349
+ return `npm install ${PACKAGE_NAME}@${target}`;
350
+ }
351
+
352
+ /**
353
+ * Default `npmUpdate` seam: install the resolved target version. The install
354
+ * rewrites `package.json` / the lockfile on disk (left staged for the
355
+ * operator); this performs no git mutation.
356
+ *
357
+ * The package manager is auto-detected from `cwd`'s lockfile (Story #3575) so
358
+ * the bump lands in the operator's real lockfile rather than running
359
+ * `npm install` against a pnpm/yarn-managed tree. The install routes through
360
+ * the shared `runInstallCommand` helper from `lib/install-cmd-parser.js`, which
361
+ * tokenizes the command and spawns with `shell: process.platform === 'win32'`
362
+ * so the Windows `.cmd` shim resolves under CVE-2024-27980 — the win32 shell
363
+ * handling and tokenization are reused, not re-implemented here. The resolved
364
+ * argv is a fixed vector; an `--install-cmd` override is tokenized and escaped
365
+ * per-arg by the parser even when the win32 shell flag is required.
366
+ *
367
+ * On any install failure the thrown error names the detected package manager's
368
+ * own `install` command so the operator can restore `node_modules` to a
369
+ * consistent state — `mandrel update` never silently leaves a half-mutated
370
+ * tree (Story #3575 AC-4).
371
+ *
372
+ * @param {string} target - The version to install.
373
+ * @param {{
374
+ * installCmd?: string,
375
+ * runInstall?: typeof runInstallCommand,
376
+ * cwd?: string,
377
+ * fs?: typeof nodeFs,
378
+ * }} [opts]
379
+ * @returns {void}
380
+ */
381
+ export function defaultNpmUpdate(
382
+ target,
383
+ {
384
+ installCmd,
385
+ runInstall = runInstallCommand,
386
+ cwd = process.cwd(),
387
+ fs = nodeFs,
388
+ } = {},
389
+ ) {
390
+ const detected = detectPackageManager(cwd, fs);
391
+ const cmd = resolveInstallCmd(target, installCmd, detected);
392
+ const repairHint =
393
+ `\n → If node_modules looks wrong, run \`${repairInstallCommand(detected.packageManager)}\`` +
394
+ ' to restore it to a consistent state.';
395
+ let r;
396
+ try {
397
+ r = runInstall(cmd, cwd);
398
+ } catch (err) {
399
+ throw new Error(
400
+ `mandrel update: install command \`${cmd}\` failed to spawn: ${err.message}${repairHint}`,
401
+ );
402
+ }
403
+ if (r.status !== 0) {
404
+ const snippet = (r.stderr || '').trim().slice(0, 200);
405
+ throw new Error(
406
+ `mandrel update: install command \`${cmd}\` exited ${r.status}: ${snippet}${repairHint}`,
407
+ );
408
+ }
409
+ }
410
+
411
+ /**
412
+ * Default `surfaceChangelog` seam: print the `docs/CHANGELOG.md` section(s)
413
+ * covering the applied version range `(current, target]`. The changelog is
414
+ * authored by release-please with `## [<version>](…)` section headers; this
415
+ * prints every section whose version is newer than `current` and no newer than
416
+ * `target`.
417
+ *
418
+ * Degrades gracefully (warns, never throws) when the file is absent or no
419
+ * matching section is found — surfacing the changelog is best-effort and must
420
+ * never fail an otherwise-successful upgrade.
421
+ *
422
+ * @param {string} target - The applied target version.
423
+ * @param {{
424
+ * current?: string,
425
+ * changelogPath?: string,
426
+ * fs?: typeof nodeFs,
427
+ * write?: (s: string) => void,
428
+ * writeErr?: (s: string) => void,
429
+ * }} [opts]
430
+ * @returns {void}
431
+ */
432
+ function defaultSurfaceChangelog(
433
+ target,
434
+ {
435
+ current,
436
+ changelogPath = path.join(resolveProjectRoot(), 'docs', 'CHANGELOG.md'),
437
+ fs = nodeFs,
438
+ write = (s) => process.stdout.write(s),
439
+ writeErr = (s) => process.stderr.write(s),
440
+ } = {},
441
+ ) {
442
+ let raw;
443
+ try {
444
+ raw = fs.readFileSync(changelogPath, 'utf8');
445
+ } catch {
446
+ writeErr(
447
+ `mandrel update: changelog not found at ${changelogPath} — skipping changelog surface.\n`,
448
+ );
449
+ return;
450
+ }
451
+
452
+ const sections = parseChangelogSections(raw);
453
+ const relevant = sections.filter((s) => {
454
+ const aboveFloor = current ? compareVersions(s.version, current) > 0 : true;
455
+ const atOrBelowTarget = compareVersions(s.version, target) <= 0;
456
+ return aboveFloor && atOrBelowTarget;
457
+ });
458
+
459
+ if (relevant.length === 0) {
460
+ writeErr(
461
+ `mandrel update: no CHANGELOG section found for v${target} — skipping changelog surface.\n`,
462
+ );
463
+ return;
464
+ }
465
+
466
+ write(`\nChangelog for v${target}:\n`);
467
+ for (const section of relevant) {
468
+ write(`${section.body.trimEnd()}\n`);
469
+ }
470
+ }
471
+
472
+ /**
473
+ * Split a release-please `CHANGELOG.md` into `{ version, body }` sections keyed
474
+ * by the `## [<version>]…` headers. Each `body` includes the header line and
475
+ * everything up to (but not including) the next version header.
476
+ *
477
+ * @param {string} raw
478
+ * @returns {Array<{ version: string, body: string }>}
479
+ */
480
+ function parseChangelogSections(raw) {
481
+ const lines = String(raw).split('\n');
482
+ const headerRe = /^## \[(\d+\.\d+\.\d+)\]/;
483
+ const sections = [];
484
+ let curVersion = null;
485
+ let curLines = [];
486
+
487
+ const flush = () => {
488
+ if (curVersion) {
489
+ sections.push({ version: curVersion, body: curLines.join('\n') });
490
+ }
491
+ };
492
+
493
+ for (const line of lines) {
494
+ const m = headerRe.exec(line);
495
+ if (m) {
496
+ flush();
497
+ curVersion = m[1];
498
+ curLines = [line];
499
+ } else if (curVersion) {
500
+ curLines.push(line);
501
+ }
502
+ }
503
+ flush();
504
+ return sections;
505
+ }
506
+
507
+ /**
508
+ * Default doctor seam: run every check in the registry sequentially and
509
+ * report whether all passed. Mirrors lib/cli/doctor.js's pass accounting
510
+ * without the formatted report (the orchestrator owns its own output).
511
+ *
512
+ * @param {{ checks?: typeof registry }} [opts]
513
+ * @returns {Promise<{ ok: boolean, results: Array<{ name: string, ok: boolean }> }>}
514
+ */
515
+ async function defaultRunDoctor({ checks = registry } = {}) {
516
+ const results = [];
517
+ for (const check of checks) {
518
+ const r = await check.run();
519
+ results.push({ name: check.name, ok: Boolean(r.ok) });
520
+ }
521
+ return { ok: results.every((r) => r.ok), results };
522
+ }
523
+
524
+ /**
525
+ * The ordered step names the orchestrator drives on a non-major bump. Shared
526
+ * by the live path and the `--dry-run` plan printout so the two never drift.
527
+ */
528
+ const STEP_PLAN = ['npm-update', 'runSync', 'runMigrations', 'doctor'];
529
+
530
+ /**
531
+ * Extract the `--install-cmd "<cmd>"` value from the subcommand argv. Accepts
532
+ * both the space form (`--install-cmd npm install …`, captured as the single
533
+ * following token group) and the `=` form (`--install-cmd="<cmd>"`). Returns
534
+ * `undefined` when the flag is absent so the default package manager is used.
535
+ *
536
+ * The argv tokenizer hands us a pre-split array; with the space form the shell
537
+ * has already collapsed a quoted value into one element, so the immediate next
538
+ * token is the full command string.
539
+ *
540
+ * @param {string[]} argv
541
+ * @returns {string | undefined}
542
+ */
543
+ function parseInstallCmdFlag(argv) {
544
+ for (let i = 0; i < argv.length; i += 1) {
545
+ const arg = argv[i];
546
+ if (arg === '--install-cmd') {
547
+ return argv[i + 1];
548
+ }
549
+ if (arg.startsWith('--install-cmd=')) {
550
+ return arg.slice('--install-cmd='.length);
551
+ }
552
+ }
553
+ return undefined;
554
+ }
555
+
556
+ /**
557
+ * Print the major-gate refusal: the available version, the runbook pointer,
558
+ * and the re-run hint. No effectful seam runs after this.
559
+ *
560
+ * @param {string} target
561
+ * @param {(s: string) => void} writeErr
562
+ */
563
+ function emitMajorRefusal(target, writeErr) {
564
+ writeErr(
565
+ `mandrel update: a newer MAJOR version (${target}) is available; ` +
566
+ 'this is a breaking upgrade.\n' +
567
+ ` → Review ${RUNBOOK_PATH}, then re-run with --major to apply it.\n`,
568
+ );
569
+ }
570
+
571
+ /**
572
+ * Run the `mandrel update` orchestration cycle.
573
+ *
574
+ * @param {{
575
+ * argv?: string[],
576
+ * currentVersion?: string | (() => string),
577
+ * resolveTargetVersion?: () => (string | Promise<string>),
578
+ * npmUpdate?: (version: string, opts: { installCmd?: string }) => unknown | Promise<unknown>,
579
+ * runSync?: typeof defaultRunSync,
580
+ * runMigrations?: typeof defaultRunMigrations,
581
+ * runDoctor?: typeof defaultRunDoctor,
582
+ * surfaceChangelog?: (version: string) => unknown | Promise<unknown>,
583
+ * write?: (s: string) => void,
584
+ * writeErr?: (s: string) => void,
585
+ * exit?: (code: number) => void,
586
+ * }} [opts]
587
+ * @returns {Promise<{
588
+ * ok: boolean,
589
+ * action: 'updated' | 'declined-major' | 'dry-run' | 'up-to-date' | 'doctor-failed',
590
+ * currentVersion: string,
591
+ * targetVersion: string | null,
592
+ * major: boolean,
593
+ * stepsRun: string[],
594
+ * dryRun: boolean,
595
+ * }>}
596
+ */
597
+ export async function runUpdate({
598
+ argv = [],
599
+ currentVersion,
600
+ resolveTargetVersion,
601
+ npmUpdate,
602
+ runSync = defaultRunSync,
603
+ runMigrations = defaultRunMigrations,
604
+ runDoctor = defaultRunDoctor,
605
+ surfaceChangelog,
606
+ write = (s) => process.stdout.write(s),
607
+ writeErr = (s) => process.stderr.write(s),
608
+ exit = (code) => process.exit(code),
609
+ } = {}) {
610
+ const dryRun = argv.includes('--dry-run');
611
+ const allowMajor = argv.includes('--major');
612
+ const installCmd = parseInstallCmdFlag(argv);
613
+
614
+ const current =
615
+ typeof currentVersion === 'function'
616
+ ? currentVersion()
617
+ : (currentVersion ?? defaultCurrentVersion());
618
+
619
+ if (typeof resolveTargetVersion !== 'function') {
620
+ throw new Error(
621
+ 'mandrel update: resolveTargetVersion seam is required to determine the newest version',
622
+ );
623
+ }
624
+ const target = String(await resolveTargetVersion());
625
+
626
+ const major = crossesMajor(current, target);
627
+
628
+ // --- Major gate -----------------------------------------------------------
629
+ // A major crossing without --major is refused outright: no npm-update, no
630
+ // sync, no migration, no doctor — print the runbook pointer and exit non-zero.
631
+ if (major && !allowMajor) {
632
+ emitMajorRefusal(target, writeErr);
633
+ exit(1);
634
+ return {
635
+ ok: false,
636
+ action: 'declined-major',
637
+ currentVersion: current,
638
+ targetVersion: target,
639
+ major: true,
640
+ stepsRun: [],
641
+ dryRun,
642
+ };
643
+ }
644
+
645
+ // --- No-op short-circuit --------------------------------------------------
646
+ // Already on (or ahead of) the newest version: nothing to apply.
647
+ if (compareVersions(target, current) <= 0) {
648
+ write(`✅ Already up to date (v${current} is the newest version).\n`);
649
+ return {
650
+ ok: true,
651
+ action: 'up-to-date',
652
+ currentVersion: current,
653
+ targetVersion: target,
654
+ major,
655
+ stepsRun: [],
656
+ dryRun,
657
+ };
658
+ }
659
+
660
+ // --- Dry run --------------------------------------------------------------
661
+ // Print the resolved target and the ordered step plan; invoke no seam and
662
+ // write nothing to disk.
663
+ if (dryRun) {
664
+ write(`mandrel update — planned upgrade v${current} → v${target}\n`);
665
+ if (major) {
666
+ write(' (major upgrade — --major supplied)\n');
667
+ }
668
+ STEP_PLAN.forEach((step, i) => {
669
+ write(` ${i + 1}. ${step}\n`);
670
+ });
671
+ write(' 5. surface changelog\n');
672
+ write('Dry run: no files written, no dependency bumped.\n');
673
+ return {
674
+ ok: true,
675
+ action: 'dry-run',
676
+ currentVersion: current,
677
+ targetVersion: target,
678
+ major,
679
+ stepsRun: [],
680
+ dryRun: true,
681
+ };
682
+ }
683
+
684
+ // --- Major runbook (inline, when --major applies) -------------------------
685
+ if (major) {
686
+ write(
687
+ `Applying MAJOR upgrade v${current} → v${target} (--major). ` +
688
+ `Review the runbook: ${RUNBOOK_PATH}\n`,
689
+ );
690
+ } else {
691
+ write(`Updating v${current} → v${target}…\n`);
692
+ }
693
+
694
+ const stepsRun = [];
695
+
696
+ // 1. npm update — bump the dependency. The lockfile change is left STAGED
697
+ // on disk; this module never commits.
698
+ if (typeof npmUpdate !== 'function') {
699
+ throw new Error(
700
+ 'mandrel update: npmUpdate seam is required to bump the dependency',
701
+ );
702
+ }
703
+ await npmUpdate(target, { installCmd });
704
+ stepsRun.push('npm-update');
705
+
706
+ // 2. runSync — re-materialize ./.agents/ from the freshly installed payload.
707
+ runSync({ argv: [] });
708
+ stepsRun.push('runSync');
709
+
710
+ // 3. runMigrations — apply version-keyed steps for the crossed range.
711
+ runMigrations({ fromVersion: current, toVersion: target, ctx: {} });
712
+ stepsRun.push('runMigrations');
713
+
714
+ // 4. doctor — verify the resulting install.
715
+ const doctor = await runDoctor();
716
+ stepsRun.push('doctor');
717
+
718
+ // 5. surface the target changelog (best-effort; optional seam).
719
+ if (typeof surfaceChangelog === 'function') {
720
+ await surfaceChangelog(target);
721
+ }
722
+
723
+ if (!doctor.ok) {
724
+ const failed = doctor.results.filter((r) => !r.ok).map((r) => r.name);
725
+ writeErr(
726
+ `mandrel update: upgraded to v${target} but doctor reported failures: ` +
727
+ `${failed.join(', ')}\n` +
728
+ ' → Run `mandrel doctor` for remedies.\n',
729
+ );
730
+ exit(1);
731
+ return {
732
+ ok: false,
733
+ action: 'doctor-failed',
734
+ currentVersion: current,
735
+ targetVersion: target,
736
+ major,
737
+ stepsRun,
738
+ dryRun: false,
739
+ };
740
+ }
741
+
742
+ write(`✅ Updated to v${target}. The lockfile bump is staged for review.\n`);
743
+ return {
744
+ ok: true,
745
+ action: 'updated',
746
+ currentVersion: current,
747
+ targetVersion: target,
748
+ major,
749
+ stepsRun,
750
+ dryRun: false,
751
+ };
752
+ }
753
+
754
+ /**
755
+ * Default export consumed by `bin/mandrel.js`.
756
+ *
757
+ * Wires the production-default seams that `runUpdate` leaves injectable:
758
+ * - `resolveTargetVersion` probes the newest published `mandrel`
759
+ * version through the daily freshness cache (`version-check.js#isStale`),
760
+ * which ALSO populates `temp/version-check.json` — the cache the
761
+ * `version-current` doctor advisory reads.
762
+ * - `npmUpdate` runs the install command — auto-detected from the project
763
+ * lockfile (`pnpm`/`yarn`/`npm`), or the `--install-cmd` override —
764
+ * through the shared `runInstallCommand` helper — no git mutation;
765
+ * lockfile left staged.
766
+ * - `surfaceChangelog` prints the relevant `docs/CHANGELOG.md` section(s)
767
+ * for the applied range, degrading gracefully when the file is absent.
768
+ *
769
+ * Every seam stays injectable on `runUpdate`; these are merely the
770
+ * no-seam-provided fallbacks, so the existing seam-driven tests stay green.
771
+ * `--major` / `--dry-run` / `--install-cmd` are parsed from `argv` by
772
+ * `runUpdate` itself.
773
+ *
774
+ * The second `deps` argument exposes the **process boundaries** the production
775
+ * defaults shell out across (`versionRunner` = `npm view`, `runInstall` =
776
+ * the install spawn) plus `fs` / `cachePath` / `now`, so the entrypoint can be
777
+ * driven end-to-end with the network/npm boundary stubbed and no real I/O.
778
+ * `bin/mandrel.js` calls `run(argv)` with no `deps`, getting the production
779
+ * wiring; tests pass fakes. The `deps` surface is NOT part of the public
780
+ * subcommand contract — `bin/mandrel.js` only ever supplies `argv`.
781
+ *
782
+ * @param {string[]} argv - Subcommand arguments (after `mandrel update`).
783
+ * @param {{
784
+ * currentVersion?: string,
785
+ * cachePath?: string,
786
+ * fs?: typeof nodeFs,
787
+ * now?: Date,
788
+ * versionRunner?: () => string,
789
+ * runInstall?: (installCmd: string, cwd: string) => { status: number, stderr: string },
790
+ * changelogPath?: string,
791
+ * runUpdate?: typeof runUpdate,
792
+ * runSync?: typeof defaultRunSync,
793
+ * runMigrations?: typeof defaultRunMigrations,
794
+ * runDoctor?: typeof defaultRunDoctor,
795
+ * write?: (s: string) => void,
796
+ * writeErr?: (s: string) => void,
797
+ * exit?: (code: number) => void,
798
+ * log?: (msg: string) => void,
799
+ * }} [deps]
800
+ * @returns {Promise<void>}
801
+ */
802
+ export default async function run(argv = [], deps = {}) {
803
+ const {
804
+ fs = nodeFs,
805
+ cachePath,
806
+ now,
807
+ versionRunner,
808
+ runInstall,
809
+ changelogPath,
810
+ runUpdate: runUpdateImpl = runUpdate,
811
+ runSync,
812
+ runMigrations,
813
+ runDoctor,
814
+ write,
815
+ writeErr,
816
+ exit,
817
+ log,
818
+ } = deps;
819
+
820
+ const current = deps.currentVersion ?? defaultCurrentVersion(fs);
821
+
822
+ await runUpdateImpl({
823
+ argv,
824
+ currentVersion: current,
825
+ resolveTargetVersion: () =>
826
+ defaultResolveTargetVersion({
827
+ ...(cachePath ? { cachePath } : {}),
828
+ fs,
829
+ ...(versionRunner ? { runner: versionRunner } : {}),
830
+ ...(now ? { now } : {}),
831
+ ...(log ? { log } : {}),
832
+ }),
833
+ npmUpdate: (target, { installCmd } = {}) =>
834
+ defaultNpmUpdate(target, {
835
+ ...(installCmd ? { installCmd } : {}),
836
+ ...(runInstall ? { runInstall } : {}),
837
+ fs,
838
+ }),
839
+ surfaceChangelog: (target) =>
840
+ defaultSurfaceChangelog(target, {
841
+ current,
842
+ fs,
843
+ ...(changelogPath ? { changelogPath } : {}),
844
+ ...(write ? { write } : {}),
845
+ ...(writeErr ? { writeErr } : {}),
846
+ }),
847
+ ...(runSync ? { runSync } : {}),
848
+ ...(runMigrations ? { runMigrations } : {}),
849
+ ...(runDoctor ? { runDoctor } : {}),
850
+ ...(write ? { write } : {}),
851
+ ...(writeErr ? { writeErr } : {}),
852
+ ...(exit ? { exit } : {}),
853
+ });
854
+ }