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,733 @@
1
+ /**
2
+ * refresh-service.js — Unified Baseline Refresh Service entry point
3
+ * (Story #2197, Epic #2173).
4
+ *
5
+ * `refreshBaseline()` is the single funnel through which every baseline
6
+ * regeneration (maintainability, crap, coverage) must flow. Callers that
7
+ * previously assembled their own envelopes and called `fs.writeFileSync`
8
+ * MUST migrate to this entry point — Stories 3/4/5 of Epic #2173 do that
9
+ * migration; Story #2197 only lands the service surface and tests.
10
+ *
11
+ * The service is **scoring-agnostic**: it does not itself walk the
12
+ * filesystem to compute MI / CRAP / coverage scores. Scoring is provided
13
+ * by the per-kind default scorers resolved lazily via `resolveDefaultScorer`
14
+ * (built with the project config resolved against `cwd`) and, in tests or
15
+ * production wiring, injected via the `scorer` option for hermetic
16
+ * determinism. The service is the policy layer:
17
+ *
18
+ * 1. Validate the input contract.
19
+ * 2. Resolve the scope (explicit list / diff-derived / full).
20
+ * 3. Read the prior envelope from `writePath` (if present).
21
+ * 4. Run the kind's scorer over the in-scope file list.
22
+ * 5. Canonicalize every persisted row path via `canonicalizeBaselinePath()`
23
+ * (Story #2192) before handing off to the shared `writer.write()`.
24
+ * 6. Pass `prior` + `scope` to `writer.write()` so out-of-scope rows are
25
+ * preserved byte-for-byte (Task #2209) and structural-equality
26
+ * short-circuits return the prior envelope unchanged.
27
+ * 7. Atomically serialise the resulting envelope to `writePath`.
28
+ *
29
+ * Public API (Task #2203, AC-1 / AC-2 / AC-7):
30
+ *
31
+ * refreshBaseline({
32
+ * kind, // 'maintainability' | 'crap' | 'coverage' REQUIRED
33
+ * baseRef, // git ref to diff against; default 'origin/main'
34
+ * headRef, // git ref under inspection; default 'HEAD'
35
+ * scopeFiles, // Array<string> | null
36
+ * // - Array: use verbatim as the in-scope file set.
37
+ * // - null + !fullScope: derive via `git diff
38
+ * // --name-only baseRef..headRef` filtered by kind
39
+ * // predicate (Task #2207).
40
+ * // - null + fullScope=true: ignore scope, regenerate
41
+ * // every row.
42
+ * epsilon, // per-kind stabilization tolerance (number | undefined)
43
+ * fullScope, // boolean; default false. When true, scopeFiles MUST
44
+ * // be null and the whole baseline is regenerated.
45
+ * writePath, // absolute path to baselines/<kind>.json REQUIRED
46
+ * scorer, // INTERNAL/TESTING: override the kind's scorer.
47
+ * // Signature: (files: string[], opts) =>
48
+ * // Promise<Array<row>> | Array<row>
49
+ * fs, // INTERNAL/TESTING: inject fs impl for read/write.
50
+ * gitDiff, // INTERNAL/TESTING: inject diff-derivation impl with
51
+ * // signature ({ baseRef, headRef, cwd }) =>
52
+ * // Iterable<string>
53
+ * cwd, // working directory for git diff; default process.cwd()
54
+ * generatedAt, // optional pinned timestamp (test determinism); falls
55
+ * // back to MANDREL_BASELINE_GENERATED_AT, then now().
56
+ * requireRowsForScopeFiles, // optional fail-loud guard for Story-close
57
+ * requiredScopeFilePredicate, // optional predicate to narrow guarded files
58
+ * }) -> Promise<{
59
+ * kind, writePath, scope: { mode, ref?, files: string[] },
60
+ * envelope, wrote: boolean
61
+ * }>
62
+ *
63
+ * Acceptance contract:
64
+ *
65
+ * AC-1: All callers that produce a maintainability/crap/coverage baseline
66
+ * go through refreshBaseline(). Enforced by Task #2208 invariant.
67
+ * AC-2: scopeFiles=null && !fullScope -> diff-derived scope (Task #2207).
68
+ * AC-4: Out-of-scope rows + their updatedAt fields are preserved byte-
69
+ * for-byte (Task #2209).
70
+ * AC-7: All persisted paths go through canonicalizeBaselinePath().
71
+ *
72
+ * @module .agents/scripts/lib/baselines/refresh-service
73
+ */
74
+
75
+ import { execFile as nodeExecFile } from 'node:child_process';
76
+ import nodeFs from 'node:fs';
77
+ import { createRequire } from 'node:module';
78
+ import path from 'node:path';
79
+ import { promisify } from 'node:util';
80
+ import { getQuality, resolveConfig } from '../config-resolver.js';
81
+ import {
82
+ buildScopePredicate,
83
+ scoreCoverageFinal,
84
+ } from '../coverage-baseline.js';
85
+ import { loadCoverage } from '../coverage-utils.js';
86
+ import {
87
+ resolveEscomplexVersion,
88
+ resolveTsTranspilerVersion,
89
+ scanAndScore,
90
+ } from '../crap-utils.js';
91
+ import {
92
+ calculateAll as calculateAllMi,
93
+ scanDirectory as scanDirectoryMi,
94
+ } from '../maintainability-utils.js';
95
+ import { filterExcludedRows } from './kinds/maintainability.js';
96
+ import { canonicalizeBaselinePath } from './path-canon.js';
97
+ import {
98
+ write as writeEnvelope,
99
+ writeFile as writeEnvelopeFile,
100
+ } from './writer.js';
101
+
102
+ const nodeRequire = createRequire(import.meta.url);
103
+
104
+ const execFileAsync = promisify(nodeExecFile);
105
+
106
+ /**
107
+ * Kinds the refresh service knows how to dispatch. Stays in lockstep with
108
+ * the per-kind modules under `.agents/scripts/lib/baselines/kinds/`.
109
+ */
110
+ const SUPPORTED_KINDS = Object.freeze(['maintainability', 'crap', 'coverage']);
111
+
112
+ /**
113
+ * Per-kind file-extension predicate for diff-scope derivation (Task #2207).
114
+ * Only files whose extension matches the kind's scorer surface are admitted
115
+ * into the diff-derived scope; this prevents unrelated diffs (docs, JSON
116
+ * fixtures, schema files) from triggering a no-op rescore.
117
+ *
118
+ * The predicates intentionally accept canonical, forward-slash POSIX paths
119
+ * only — every caller funnels through `canonicalizeBaselinePath()` first.
120
+ *
121
+ * @type {Record<string, (p: string) => boolean>}
122
+ */
123
+ const KIND_FILE_PREDICATES = Object.freeze({
124
+ maintainability: (p) => /\.(?:m?[jt]sx?)$/i.test(p),
125
+ crap: (p) => /\.(?:m?[jt]sx?)$/i.test(p),
126
+ coverage: (p) => /\.(?:m?[jt]sx?)$/i.test(p),
127
+ });
128
+
129
+ /**
130
+ * Resolve the normalized quality block for a kind from a `config` /
131
+ * `quality` pair. The default scorers MUST read the same canonical,
132
+ * defaulted shape that the production scorers (`refresh-commit.js#buildKindScorer`,
133
+ * `update-crap-baseline.js`) consume — i.e. the `getQuality(config)` output,
134
+ * not the raw `config.delivery.quality.gates.<kind>` path. The raw path is
135
+ * un-defaulted (e.g. it lacks `requireCoverage` / `coveragePath`), so reading
136
+ * it directly is exactly the construction inconsistency Story #3694 fixes.
137
+ *
138
+ * Precedence: an explicitly supplied `quality` block wins; otherwise derive
139
+ * it from `config` via `getQuality`; otherwise fall back to `{}`.
140
+ *
141
+ * @param {{ quality?: object, config?: object }} opts
142
+ * @returns {object}
143
+ */
144
+ function resolveQualityBlock({ quality, config } = {}) {
145
+ if (quality && typeof quality === 'object') return quality;
146
+ if (config && typeof config === 'object') return getQuality(config) ?? {};
147
+ return {};
148
+ }
149
+
150
+ /**
151
+ * Build the default CRAP scorer. Scans configured target directories
152
+ * (full-scope) or the diff-derived file list, loads coverage-final.json,
153
+ * and runs `scanAndScore` to produce row-shape objects ready for the writer.
154
+ *
155
+ * Reads its `targetDirs` / `ignoreGlobs` / `requireCoverage` / `coveragePath`
156
+ * from the normalized quality block (Story #3694). The lazy default resolver
157
+ * (`resolveDefaultScorer`) passes the resolved project quality block so the
158
+ * config-less default no longer silently drops rows.
159
+ *
160
+ * Exposed for unit tests that need to inspect the built scorer shape; the
161
+ * production caller is the internal `resolveDefaultScorer` resolver below.
162
+ *
163
+ * @param {{ cwd: string, config?: object, quality?: object }} opts
164
+ * @returns {(files: string[], opts: object) => Promise<object[]>}
165
+ */
166
+ function buildDefaultCrapScorer({ cwd, config, quality } = {}) {
167
+ // Config is optional: callers that don't pass it get reasonable defaults.
168
+ const crapCfg = resolveQualityBlock({ quality, config })?.crap ?? {};
169
+ const targetDirs = Array.isArray(crapCfg.targetDirs)
170
+ ? crapCfg.targetDirs
171
+ : [];
172
+ const ignoreGlobs = Array.isArray(crapCfg.ignoreGlobs)
173
+ ? crapCfg.ignoreGlobs
174
+ : [];
175
+ const requireCoverage = crapCfg.requireCoverage !== false;
176
+ const coverageRelPath =
177
+ crapCfg.coveragePath ?? 'coverage/coverage-final.json';
178
+ return async (files, opts) => {
179
+ const effectiveCwd = opts?.cwd ?? cwd ?? process.cwd();
180
+ const coverageAbs = path.isAbsolute(coverageRelPath)
181
+ ? coverageRelPath
182
+ : path.resolve(effectiveCwd, coverageRelPath);
183
+ const coverage = loadCoverage(coverageAbs);
184
+ if (!coverage && requireCoverage) return [];
185
+ const scopeFiles = opts?.fullScope ? null : (files ?? null);
186
+ const { rows } = await scanAndScore({
187
+ targetDirs,
188
+ coverage,
189
+ requireCoverage,
190
+ cwd: effectiveCwd,
191
+ ignoreGlobs,
192
+ scopeFiles,
193
+ });
194
+ // Stamp version probes (satisfies coverage even when caller doesn't need
195
+ // the values — the writer stamps kernelVersion from the crap kind module).
196
+ resolveEscomplexVersion(effectiveCwd);
197
+ resolveTsTranspilerVersion();
198
+ return (rows ?? []).filter(
199
+ (r) => typeof r?.crap === 'number' && Number.isFinite(r.crap),
200
+ );
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Build the default coverage scorer. Reads coverage-final.json, applies
206
+ * the c8 scope predicate from `.c8rc.cjs`, and converts the per-file
207
+ * coverage percentages into rows in the `{ path, lines, branches,
208
+ * functions }` shape the writer expects.
209
+ *
210
+ * `.c8rc.cjs` is optional: when absent the scorer admits all files.
211
+ *
212
+ * @param {{ cwd: string }} opts
213
+ * @returns {(files: string[], opts: object) => object[]}
214
+ */
215
+ function buildDefaultCoverageScorer({ cwd } = {}) {
216
+ return (files, opts) => {
217
+ const effectiveCwd = opts?.cwd ?? cwd ?? process.cwd();
218
+ const coverageFinalPath = path.resolve(
219
+ effectiveCwd,
220
+ 'coverage/coverage-final.json',
221
+ );
222
+ let raw;
223
+ try {
224
+ raw = JSON.parse(nodeFs.readFileSync(coverageFinalPath, 'utf-8'));
225
+ } catch {
226
+ return [];
227
+ }
228
+ let c8Scope;
229
+ try {
230
+ const c8rcPath = path.resolve(effectiveCwd, '.c8rc.cjs');
231
+ const c8Config = nodeRequire(c8rcPath);
232
+ c8Scope = buildScopePredicate({
233
+ include: c8Config.include ?? [],
234
+ exclude: c8Config.exclude ?? [],
235
+ });
236
+ } catch {
237
+ c8Scope = buildScopePredicate({});
238
+ }
239
+ const scores = scoreCoverageFinal({
240
+ raw,
241
+ cwd: effectiveCwd,
242
+ scope: c8Scope,
243
+ });
244
+ // In diff mode, further narrow to the in-scope file list so only changed
245
+ // files are re-scored (out-of-scope rows are preserved by the service).
246
+ const inScope =
247
+ !opts?.fullScope && Array.isArray(files) && files.length > 0
248
+ ? new Set(files)
249
+ : null;
250
+ return Object.entries(scores)
251
+ .filter(([relPath]) => inScope === null || inScope.has(relPath))
252
+ .map(([relPath, score]) => ({
253
+ path: relPath,
254
+ lines: score?.lines ?? 0,
255
+ branches: score?.branches ?? 0,
256
+ functions: score?.functions ?? 0,
257
+ }));
258
+ };
259
+ }
260
+
261
+ /**
262
+ * Build the default maintainability scorer. Full-scope walks all configured
263
+ * target directories; diff-scope resolves just the in-scope files.
264
+ *
265
+ * Reads its `targetDirs` / `ignoreGlobs` from the normalized quality block
266
+ * (Story #3694), mirroring `buildDefaultCrapScorer` and the production
267
+ * `refresh-commit.js#buildKindScorer`.
268
+ *
269
+ * @param {{ cwd: string, config?: object, quality?: object }} opts
270
+ * @returns {(files: string[], opts: object) => Promise<object[]>}
271
+ */
272
+ function buildDefaultMaintainabilityScorer({ cwd, config, quality } = {}) {
273
+ const miCfg = resolveQualityBlock({ quality, config })?.maintainability ?? {};
274
+ const targetDirs = Array.isArray(miCfg.targetDirs) ? miCfg.targetDirs : [];
275
+ const ignoreGlobs = Array.isArray(miCfg.ignoreGlobs) ? miCfg.ignoreGlobs : [];
276
+ return async (files, opts) => {
277
+ const effectiveCwd = opts?.cwd ?? cwd ?? process.cwd();
278
+ const targetAbsDirs = targetDirs.map((dir) =>
279
+ path.isAbsolute(dir) ? dir : path.resolve(effectiveCwd, dir),
280
+ );
281
+ let sourceList;
282
+ if (opts?.fullScope) {
283
+ sourceList = [];
284
+ for (const abs of targetAbsDirs) {
285
+ scanDirectoryMi(abs, sourceList, { cwd: effectiveCwd, ignoreGlobs });
286
+ }
287
+ } else {
288
+ sourceList = [];
289
+ for (const rel of files ?? []) {
290
+ const abs = path.resolve(effectiveCwd, rel);
291
+ const underTarget = targetAbsDirs.some(
292
+ (root) => abs === root || abs.startsWith(`${root}${path.sep}`),
293
+ );
294
+ if (underTarget) sourceList.push(abs);
295
+ }
296
+ }
297
+ const scores = await calculateAllMi(sourceList);
298
+ return filterExcludedRows(
299
+ Object.entries(scores).map(([p, mi]) => {
300
+ const rel = path.isAbsolute(p) ? path.relative(effectiveCwd, p) : p;
301
+ return { path: rel.split(path.sep).join('/'), mi };
302
+ }),
303
+ );
304
+ };
305
+ }
306
+
307
+ /**
308
+ * Per-kind default-scorer builders. Story #3658 completes the Epic #2173
309
+ * migration by wiring real default scorers for all three kinds so the service
310
+ * is self-contained: callers may still inject a `scorer` via the options bag
311
+ * (used by auto-refresh-runner and tests), but no scorer injection is required
312
+ * for production invocations.
313
+ *
314
+ * Story #3694: the builders are invoked **lazily** by `resolveDefaultScorer`
315
+ * with the project config resolved against the call's `cwd`, rather than being
316
+ * frozen once at module-load with `{ cwd: process.cwd() }` and no `config`.
317
+ * The previous eager table built every scorer with no config, so the crap and
318
+ * maintainability scorers ran with empty `targetDirs`/`ignoreGlobs` and
319
+ * silently dropped valid rows. Lazy resolution honours both the call's `cwd`
320
+ * and the resolved `crap.targetDirs`/`ignoreGlobs`/`requireCoverage` (and the
321
+ * maintainability equivalents).
322
+ *
323
+ * @type {Record<string, (input: { cwd: string, config?: object, quality?: object }) => ((files: string[], opts: object) => Promise<object[]> | object[])>}
324
+ */
325
+ const KIND_SCORER_BUILDERS = Object.freeze({
326
+ maintainability: buildDefaultMaintainabilityScorer,
327
+ crap: buildDefaultCrapScorer,
328
+ coverage: buildDefaultCoverageScorer,
329
+ });
330
+
331
+ /**
332
+ * Resolve the default scorer for `kind`, building it with the project config
333
+ * resolved against `cwd` (Story #3694). This is the production replacement for
334
+ * the old eager `KIND_SCORERS` table: it guarantees the crap and
335
+ * maintainability defaults are constructed with the resolved
336
+ * `targetDirs`/`ignoreGlobs`/`requireCoverage`, so a config-less
337
+ * `refreshBaseline({ kind: 'crap', ... })` call produces the same rows as the
338
+ * `update-crap-baseline.js` CLI rather than silently dropping them.
339
+ *
340
+ * Config resolution is best-effort: if `resolveConfig` throws (e.g. a
341
+ * malformed `.agentrc.json` under a tmp `cwd` in tests), we fall back to a
342
+ * config-less builder so the service still produces a valid (empty) envelope
343
+ * rather than crashing the refresh. The production crap/maintainability paths
344
+ * never rely on this fallback — they inject an explicit, configured scorer.
345
+ *
346
+ * @param {string} kind
347
+ * @param {{ cwd: string }} opts
348
+ * @returns {((files: string[], opts: object) => Promise<object[]> | object[]) | undefined}
349
+ */
350
+ function resolveDefaultScorer(kind, { cwd } = {}) {
351
+ const builder = KIND_SCORER_BUILDERS[kind];
352
+ if (typeof builder !== 'function') return undefined;
353
+ const effectiveCwd = cwd ?? process.cwd();
354
+ let quality;
355
+ try {
356
+ quality = getQuality(resolveConfig({ cwd: effectiveCwd })) ?? undefined;
357
+ } catch {
358
+ quality = undefined;
359
+ }
360
+ return builder({ cwd: effectiveCwd, quality });
361
+ }
362
+
363
+ /**
364
+ * Refresh the on-disk baseline for `kind`. See module preamble for the
365
+ * full contract. Returns the resulting envelope plus the resolved scope
366
+ * so callers (and tests) can assert what actually got scored.
367
+ *
368
+ * @param {{
369
+ * kind: 'maintainability' | 'crap' | 'coverage',
370
+ * baseRef?: string,
371
+ * headRef?: string,
372
+ * scopeFiles?: string[] | null,
373
+ * epsilon?: number,
374
+ * fullScope?: boolean,
375
+ * writePath: string,
376
+ * scorer?: (files: string[], opts: object) => Promise<object[]> | object[],
377
+ * fs?: typeof nodeFs,
378
+ * gitDiff?: (args: { baseRef: string, headRef: string, cwd: string }) => Iterable<string> | Promise<Iterable<string>>,
379
+ * cwd?: string,
380
+ * generatedAt?: string,
381
+ * requireRowsForScopeFiles?: boolean,
382
+ * requiredScopeFilePredicate?: (file: string) => boolean,
383
+ * }} opts
384
+ * @returns {Promise<{
385
+ * kind: string,
386
+ * writePath: string,
387
+ * scope: { mode: 'full' | 'diff' | 'explicit', ref?: string, files: string[] },
388
+ * envelope: object,
389
+ * wrote: boolean,
390
+ * }>}
391
+ */
392
+ export async function refreshBaseline(opts = {}) {
393
+ const {
394
+ kind,
395
+ baseRef = 'origin/main',
396
+ headRef = 'HEAD',
397
+ scopeFiles = null,
398
+ epsilon,
399
+ fullScope = false,
400
+ writePath,
401
+ scorer,
402
+ fs = nodeFs,
403
+ gitDiff = defaultGitDiff,
404
+ cwd = process.cwd(),
405
+ generatedAt,
406
+ requireRowsForScopeFiles = false,
407
+ requiredScopeFilePredicate,
408
+ } = opts;
409
+
410
+ validateOptions({ kind, scopeFiles, fullScope, writePath });
411
+
412
+ // Resolve the kind's scorer. Tests / production wiring inject via
413
+ // `opts.scorer`; otherwise build the default scorer lazily with the project
414
+ // config resolved against `cwd` (Story #3694) so the crap/maintainability
415
+ // defaults honour the configured targetDirs/ignoreGlobs.
416
+ const resolvedScorer = scorer ?? resolveDefaultScorer(kind, { cwd });
417
+ if (typeof resolvedScorer !== 'function') {
418
+ throw new Error(
419
+ `refreshBaseline: no scorer registered for kind "${kind}" (inject one via opts.scorer)`,
420
+ );
421
+ }
422
+
423
+ // Resolve the in-scope file set.
424
+ const scope = await resolveScope({
425
+ kind,
426
+ scopeFiles,
427
+ fullScope,
428
+ baseRef,
429
+ headRef,
430
+ gitDiff,
431
+ cwd,
432
+ });
433
+
434
+ // Score every in-scope file. For full-scope refreshes the scorer
435
+ // receives an empty `files` list and is expected to scan the whole
436
+ // target tree itself (the scorer owns the directory walk — the service
437
+ // does not, by design).
438
+ const scoredRows = await resolvedScorer(scope.files, {
439
+ kind,
440
+ fullScope: scope.mode === 'full',
441
+ baseRef,
442
+ headRef,
443
+ cwd,
444
+ });
445
+ if (!Array.isArray(scoredRows)) {
446
+ throw new TypeError(
447
+ `refreshBaseline: scorer for kind "${kind}" must return an array of rows`,
448
+ );
449
+ }
450
+
451
+ // Canonicalize every row path (Story #2192 / AC-7). The shared
452
+ // `writer.write()` already runs each row through the per-kind
453
+ // `projectRow` which calls `canonicalise()` internally, but funnelling
454
+ // through `canonicalizeBaselinePath()` here is the explicit
455
+ // service-level contract: rows leave the service with canonical keys,
456
+ // regardless of which scorer produced them.
457
+ const canonicalRows = scoredRows.map((row) => ({
458
+ ...row,
459
+ path: canonicalizeBaselinePath(row.path ?? row.file),
460
+ }));
461
+
462
+ assertRequiredScopeRows({
463
+ kind,
464
+ scope,
465
+ canonicalRows,
466
+ requireRowsForScopeFiles,
467
+ requiredScopeFilePredicate,
468
+ });
469
+
470
+ // Read the prior envelope so out-of-scope rows survive (Task #2209) and
471
+ // the structural-equality short-circuit can fire.
472
+ const priorEnvelope = readPriorEnvelope(writePath, fs);
473
+
474
+ // Hand off to the shared writer. It applies `mergeRows` (scope), then
475
+ // `applyEpsilon` (stability), then sort + rollup + envelope stamping.
476
+ const envelope = writeEnvelope({
477
+ kind,
478
+ rows: canonicalRows,
479
+ prior: priorEnvelope?.rows,
480
+ priorEnvelope,
481
+ epsilon,
482
+ scope:
483
+ scope.mode === 'full'
484
+ ? null
485
+ : { mode: 'diff', files: new Set(scope.files) },
486
+ generatedAt: generatedAt ?? process.env.MANDREL_BASELINE_GENERATED_AT,
487
+ });
488
+
489
+ // Persist iff the envelope changed. The writer's structural-equality
490
+ // short-circuit returns the prior envelope object identity-equal when
491
+ // nothing changed; in that case we skip the disk write so the on-disk
492
+ // bytes (including `generatedAt`) are preserved verbatim.
493
+ let wrote = false;
494
+ if (priorEnvelope === null || envelope !== priorEnvelope) {
495
+ writeEnvelopeFile(writePath, envelope, { fsImpl: fs });
496
+ wrote = true;
497
+ }
498
+
499
+ return {
500
+ kind,
501
+ writePath,
502
+ scope: {
503
+ mode: scope.mode,
504
+ ref: scope.ref,
505
+ files: [...scope.files],
506
+ },
507
+ envelope,
508
+ wrote,
509
+ };
510
+ }
511
+
512
+ function assertRequiredScopeRows({
513
+ kind,
514
+ scope,
515
+ canonicalRows,
516
+ requireRowsForScopeFiles,
517
+ requiredScopeFilePredicate,
518
+ }) {
519
+ if (!requireRowsForScopeFiles || scope.mode === 'full') return;
520
+ const predicate =
521
+ typeof requiredScopeFilePredicate === 'function'
522
+ ? requiredScopeFilePredicate
523
+ : () => true;
524
+ const requiredFiles = scope.files.filter(predicate);
525
+ if (requiredFiles.length === 0) return;
526
+
527
+ const rowPaths = new Set(
528
+ canonicalRows
529
+ .map((row) => row?.path)
530
+ .filter((rowPath) => typeof rowPath === 'string' && rowPath.length > 0),
531
+ );
532
+ const missing = requiredFiles.filter((file) => !rowPaths.has(file));
533
+ if (missing.length === 0) return;
534
+
535
+ throw new Error(
536
+ `refreshBaseline(${kind}): scoped file(s) produced no baseline rows: ${missing.join(', ')}. ` +
537
+ 'Run coverage/scoring for the changed files or use full-scope refresh; refusing to write a baseline that would silently drop Story-owned files.',
538
+ );
539
+ }
540
+
541
+ /**
542
+ * Default git-diff derivation for the diff-scope path. Uses `execFile`
543
+ * (no shell) and only the canonical two-dot range `baseRef..headRef` —
544
+ * triple-dot is intentionally avoided so the result reflects exactly the
545
+ * files that differ between the two refs at the time of the call.
546
+ *
547
+ * @param {{ baseRef: string, headRef: string, cwd: string }} args
548
+ * @returns {Promise<string[]>}
549
+ */
550
+ async function defaultGitDiff({ baseRef, headRef, cwd }) {
551
+ const range = `${baseRef}..${headRef}`;
552
+ try {
553
+ const { stdout } = await execFileAsync(
554
+ 'git',
555
+ ['diff', '--name-only', range],
556
+ { cwd, maxBuffer: 16 * 1024 * 1024 },
557
+ );
558
+ return stdout
559
+ .split(/\r?\n/)
560
+ .map((line) => line.trim())
561
+ .filter((line) => line.length > 0);
562
+ } catch (err) {
563
+ // A missing ref or corrupt repo is the operator's signal to inspect
564
+ // the working tree. Best-effort: emit a friction-friendly error.
565
+ throw new Error(
566
+ `refreshBaseline: git diff --name-only ${range} failed in ${cwd}: ${err.message}`,
567
+ );
568
+ }
569
+ }
570
+
571
+ /**
572
+ * Derive an in-scope file list from `git diff --name-only baseRef..headRef`
573
+ * filtered by `predicate` (Story #2197, Task #2207). Exposed as a named
574
+ * export so the diff-scope behaviour can be exercised in isolation. Every
575
+ * file returned is canonicalized via `canonicalizeBaselinePath()` before
576
+ * the predicate runs, so the predicate may assume POSIX, repo-relative
577
+ * input regardless of what shape `git diff` printed on the host platform.
578
+ *
579
+ * Pure-by-design: `gitDiff` is injected by the caller (defaults to
580
+ * `defaultGitDiff` which uses `execFile`, never a shell).
581
+ *
582
+ * @param {{
583
+ * baseRef: string,
584
+ * headRef: string,
585
+ * predicate: (canonicalPath: string) => boolean,
586
+ * gitDiff?: (args: { baseRef: string, headRef: string, cwd: string }) => Iterable<string> | Promise<Iterable<string>>,
587
+ * cwd?: string,
588
+ * }} args
589
+ * @returns {Promise<string[]>}
590
+ */
591
+ export async function deriveScopeFromDiff({
592
+ baseRef,
593
+ headRef,
594
+ predicate,
595
+ gitDiff = defaultGitDiff,
596
+ cwd = process.cwd(),
597
+ }) {
598
+ if (typeof predicate !== 'function') {
599
+ throw new TypeError('deriveScopeFromDiff: predicate must be a function');
600
+ }
601
+ const raw = await gitDiff({ baseRef, headRef, cwd });
602
+ const out = [];
603
+ for (const item of raw ?? []) {
604
+ if (typeof item !== 'string' || item.length === 0) continue;
605
+ const canonical = canonicalizeBaselinePath(item);
606
+ if (predicate(canonical)) out.push(canonical);
607
+ }
608
+ return out;
609
+ }
610
+
611
+ /**
612
+ * Look up the file predicate for `kind`. Exposed so external tests can
613
+ * verify the per-kind extension filter without depending on the private
614
+ * `KIND_FILE_PREDICATES` table.
615
+ *
616
+ * @param {string} kind
617
+ * @returns {(p: string) => boolean}
618
+ */
619
+ export function fileFilterFor(kind) {
620
+ const pred = KIND_FILE_PREDICATES[kind];
621
+ if (!pred) {
622
+ throw new Error(
623
+ `fileFilterFor: no predicate registered for kind "${kind}"`,
624
+ );
625
+ }
626
+ return pred;
627
+ }
628
+
629
+ /**
630
+ * Resolve the in-scope file set for this refresh call. Returns a flat
631
+ * `{ mode, ref?, files }` record so callers can branch on the resolution
632
+ * mode without re-deriving it from the input shape.
633
+ *
634
+ * Resolution order:
635
+ *
636
+ * 1. `fullScope === true` -> `{ mode: 'full', files: [] }`.
637
+ * 2. `scopeFiles` is an array -> `{ mode: 'explicit', files }`.
638
+ * 3. `scopeFiles === null` -> derive via `gitDiff` filtered by the kind's
639
+ * predicate -> `{ mode: 'diff', ref: baseRef..headRef, files }`.
640
+ */
641
+ async function resolveScope({
642
+ kind,
643
+ scopeFiles,
644
+ fullScope,
645
+ baseRef,
646
+ headRef,
647
+ gitDiff,
648
+ cwd,
649
+ }) {
650
+ if (fullScope) {
651
+ return { mode: 'full', files: [] };
652
+ }
653
+ if (Array.isArray(scopeFiles)) {
654
+ return {
655
+ mode: 'explicit',
656
+ files: scopeFiles.map((p) => canonicalizeBaselinePath(p)),
657
+ };
658
+ }
659
+ // Diff-derived (Task #2207).
660
+ const files = await deriveScopeFromDiff({
661
+ baseRef,
662
+ headRef,
663
+ predicate: fileFilterFor(kind),
664
+ gitDiff,
665
+ cwd,
666
+ });
667
+ return { mode: 'diff', ref: `${baseRef}..${headRef}`, files };
668
+ }
669
+
670
+ /**
671
+ * Read + JSON-parse the prior envelope at `writePath`. Returns `null` on
672
+ * any I/O or parse failure — the caller treats "no prior" as "fresh
673
+ * write" (regression-fail-safe).
674
+ *
675
+ * @param {string} writePath
676
+ * @param {typeof nodeFs} fs
677
+ * @returns {object | null}
678
+ */
679
+ function readPriorEnvelope(writePath, fs) {
680
+ let raw;
681
+ try {
682
+ raw = fs.readFileSync(writePath, 'utf8');
683
+ } catch {
684
+ return null;
685
+ }
686
+ try {
687
+ const parsed = JSON.parse(raw);
688
+ if (
689
+ parsed &&
690
+ typeof parsed === 'object' &&
691
+ !Array.isArray(parsed) &&
692
+ Array.isArray(parsed.rows) &&
693
+ parsed.rollup &&
694
+ typeof parsed.rollup === 'object'
695
+ ) {
696
+ return parsed;
697
+ }
698
+ return null;
699
+ } catch {
700
+ return null;
701
+ }
702
+ }
703
+
704
+ /**
705
+ * Validate the option bag up-front. Throws on any contract violation so a
706
+ * misuse never silently produces an empty / wrong baseline.
707
+ */
708
+ function validateOptions({ kind, scopeFiles, fullScope, writePath }) {
709
+ if (typeof kind !== 'string' || !SUPPORTED_KINDS.includes(kind)) {
710
+ throw new Error(
711
+ `refreshBaseline: unknown kind "${kind}" (supported: ${SUPPORTED_KINDS.join(', ')})`,
712
+ );
713
+ }
714
+ if (typeof writePath !== 'string' || writePath.length === 0) {
715
+ throw new TypeError(
716
+ 'refreshBaseline: writePath is required and must be a non-empty string',
717
+ );
718
+ }
719
+ if (scopeFiles !== null && !Array.isArray(scopeFiles)) {
720
+ throw new TypeError(
721
+ `refreshBaseline: scopeFiles must be null or an array (got ${typeof scopeFiles})`,
722
+ );
723
+ }
724
+ if (fullScope === true && scopeFiles !== null) {
725
+ throw new Error(
726
+ 'refreshBaseline: fullScope=true is incompatible with an explicit scopeFiles array; pass scopeFiles=null',
727
+ );
728
+ }
729
+ }
730
+
731
+ // Exposed for the lint/test invariant (Task #2208) so the guard can list
732
+ // every kind the service is contracted to dispatch without re-deriving it.
733
+ export const REFRESH_SERVICE_SUPPORTED_KINDS = SUPPORTED_KINDS;