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,370 @@
1
+ /**
2
+ * bootstrap/quality-bootstrap — Story #1401 (Epic #1386)
3
+ *
4
+ * Idempotent installer for the stabilized-quality-gates surface area on a
5
+ * project clone. Performs four additive actions, each safe to re-run:
6
+ *
7
+ * 1. Copies the `code-quality-guardrails.md` helper into the project's
8
+ * `.agents/workflows/helpers/` (no-op when the helper is already present).
9
+ * 2. Installs `.husky/pre-commit` carrying the `quality:preview` invocation
10
+ * that the framework ships, preserving any custom hook lines already in
11
+ * place. When a custom (non-framework) `pre-commit` exists, it is left
12
+ * untouched and the caller is told to merge in the snippet manually.
13
+ * 3. Adds `quality:preview` and `quality:watch` npm scripts when missing.
14
+ * Existing scripts are preserved.
15
+ * 4. Seeds `delivery.quality.codingGuardrails` and
16
+ * `delivery.quality.autoRefresh` defaults in `.agentrc.json` when
17
+ * the keys are absent. Existing values are preserved.
18
+ *
19
+ * Returns a structured summary so the bootstrap and update workflows can
20
+ * surface exactly which actions ran and which were no-ops.
21
+ *
22
+ * Exports are pure-ish (filesystem effects only via the supplied paths) so
23
+ * the test suite can drive the helper against a tmp directory.
24
+ *
25
+ * @module bootstrap/quality-bootstrap
26
+ */
27
+
28
+ import fs from 'node:fs';
29
+ import path from 'node:path';
30
+ import { getAgentrcDefaults, lookupPath } from '../config/defaults.js';
31
+ import { deepEqual } from '../json-utils.js';
32
+
33
+ /**
34
+ * The exact pre-commit body the framework ships. Kept as a single string so
35
+ * the hook-installer can detect a verbatim framework hook (overwrite-safe)
36
+ * vs a custom hook (preserve and warn).
37
+ */
38
+ export const FRAMEWORK_PRE_COMMIT = `node scripts/check-version-sync.js
39
+ npx lint-staged
40
+ # Story #1395 / Epic #1386: catch MI/CRAP drift at git-commit time so the
41
+ # agent refactors before the diff is closed. quality:preview wraps both gates
42
+ # with --changed-since HEAD --staged --json and exits non-zero on any
43
+ # threshold violation, blocking the commit and rendering the per-file delta
44
+ # table to stderr (via the gates inherited stdio).
45
+ node .agents/scripts/quality-preview.js --changed-since HEAD --staged
46
+ `;
47
+
48
+ /**
49
+ * Minimal pre-commit body for downstream projects that do not carry the
50
+ * framework's `check-version-sync.js` script. Drops that line and the
51
+ * `lint-staged` invocation (downstream may or may not have lint-staged
52
+ * configured); keeps the quality-preview line which is the load-bearing
53
+ * Epic #1386 addition.
54
+ */
55
+ export const DOWNSTREAM_PRE_COMMIT = `# Stabilized quality gates (Epic #1386 / Story #1401):
56
+ # catch MI/CRAP drift at git-commit time so the agent refactors before the
57
+ # diff is closed. quality:preview wraps both gates with --changed-since HEAD
58
+ # --staged and exits non-zero on any threshold violation, blocking the
59
+ # commit and rendering the per-file delta table to stderr.
60
+ node .agents/scripts/quality-preview.js --changed-since HEAD --staged
61
+ `;
62
+
63
+ /**
64
+ * Marker substring used to detect a framework-installed quality-preview line
65
+ * inside a pre-commit hook regardless of which body variant is in use.
66
+ */
67
+ export const PRE_COMMIT_MARKER =
68
+ 'node .agents/scripts/quality-preview.js --changed-since HEAD --staged';
69
+
70
+ /**
71
+ * Default values seeded into `delivery.quality.{codingGuardrails,autoRefresh}`
72
+ * when the keys are absent. Mirrors `.agents/docs/agentrc-reference.json` — keep in
73
+ * sync when those numbers move.
74
+ */
75
+ export const QUALITY_CONFIG_DEFAULTS = Object.freeze({
76
+ codingGuardrails: Object.freeze({
77
+ cyclomaticFlag: 8,
78
+ cyclomaticMustFix: 12,
79
+ miDropMustRefactor: 1.5,
80
+ requireSiblingTest: false,
81
+ }),
82
+ autoRefresh: Object.freeze({
83
+ enabled: true,
84
+ miDropCap: 1.5,
85
+ crapJumpCap: 5,
86
+ scope: 'diff',
87
+ }),
88
+ });
89
+
90
+ /**
91
+ * NPM scripts seeded by the bootstrap. Existing values are preserved.
92
+ */
93
+ export const QUALITY_NPM_SCRIPTS = Object.freeze({
94
+ 'quality:preview':
95
+ 'node .agents/scripts/quality-preview.js --changed-since HEAD',
96
+ 'quality:watch': 'node .agents/scripts/quality-watch.js',
97
+ });
98
+
99
+ /**
100
+ * Read JSON from a path, returning `null` when the file does not exist.
101
+ * Surfaces parse errors so callers can fail loudly on a corrupt config.
102
+ */
103
+ function readJsonIfExists(p) {
104
+ if (!fs.existsSync(p)) return null;
105
+ const raw = fs.readFileSync(p, 'utf8');
106
+ return JSON.parse(raw);
107
+ }
108
+
109
+ function writeJson(p, obj) {
110
+ fs.mkdirSync(path.dirname(p), { recursive: true });
111
+ fs.writeFileSync(p, `${JSON.stringify(obj, null, 2)}\n`, 'utf8');
112
+ }
113
+
114
+ /**
115
+ * Step 1 — Ensure the code-quality-guardrails helper is present under
116
+ * `.agents/workflows/helpers/`. When the helper already exists we report
117
+ * `already-present`. Otherwise the helper is copied from the framework source
118
+ * if available, or skipped with a `missing-source` outcome the caller can
119
+ * surface.
120
+ *
121
+ * @param {object} ctx
122
+ * @param {string} ctx.projectRoot
123
+ * @param {string} [ctx.frameworkRoot] - Path to the framework checkout
124
+ * (defaults to `<projectRoot>/.agents`). Tests pass an explicit path.
125
+ */
126
+ export function ensureGuardrailsHelper(ctx) {
127
+ const projectRoot = ctx.projectRoot;
128
+ const target = path.join(
129
+ projectRoot,
130
+ '.agents',
131
+ 'workflows',
132
+ 'helpers',
133
+ 'code-quality-guardrails.md',
134
+ );
135
+ if (fs.existsSync(target)) {
136
+ return { action: 'already-present', path: target };
137
+ }
138
+ const sourceRoot = ctx.frameworkRoot ?? path.join(projectRoot, '.agents');
139
+ const source = path.join(
140
+ sourceRoot,
141
+ 'workflows',
142
+ 'helpers',
143
+ 'code-quality-guardrails.md',
144
+ );
145
+ if (!fs.existsSync(source)) {
146
+ return { action: 'missing-source', path: target };
147
+ }
148
+ fs.mkdirSync(path.dirname(target), { recursive: true });
149
+ fs.copyFileSync(source, target);
150
+ return { action: 'copied', path: target };
151
+ }
152
+
153
+ /**
154
+ * Step 2 — Install the `.husky/pre-commit` hook. Decision tree:
155
+ *
156
+ * - No `.husky/pre-commit` file → write the requested body, action `created`.
157
+ * - File exists and already contains the quality-preview marker → no-op,
158
+ * action `already-present`.
159
+ * - File exists, does NOT contain the marker, and matches the framework
160
+ * body byte-for-byte → safe overwrite, action `updated`.
161
+ * - File exists, custom content → leave untouched and emit
162
+ * `custom-hook-skip` so the workflow can print the operator notice with
163
+ * the recommended snippet to merge in.
164
+ *
165
+ * @param {object} ctx
166
+ * @param {string} ctx.projectRoot
167
+ * @param {'framework'|'downstream'} [ctx.variant='downstream']
168
+ */
169
+ export function ensurePreCommitHook(ctx) {
170
+ const variant = ctx.variant ?? 'downstream';
171
+ const body =
172
+ variant === 'framework' ? FRAMEWORK_PRE_COMMIT : DOWNSTREAM_PRE_COMMIT;
173
+ const huskyDir = path.join(ctx.projectRoot, '.husky');
174
+ const hookPath = path.join(huskyDir, 'pre-commit');
175
+ if (!fs.existsSync(hookPath)) {
176
+ fs.mkdirSync(huskyDir, { recursive: true });
177
+ fs.writeFileSync(hookPath, body, 'utf8');
178
+ return {
179
+ action: 'created',
180
+ path: hookPath,
181
+ variant,
182
+ snippet: PRE_COMMIT_MARKER,
183
+ };
184
+ }
185
+ const existing = fs.readFileSync(hookPath, 'utf8');
186
+ if (existing.includes(PRE_COMMIT_MARKER)) {
187
+ return {
188
+ action: 'already-present',
189
+ path: hookPath,
190
+ variant,
191
+ snippet: PRE_COMMIT_MARKER,
192
+ };
193
+ }
194
+ return {
195
+ action: 'custom-hook-skip',
196
+ path: hookPath,
197
+ variant,
198
+ snippet: body,
199
+ notice:
200
+ 'Custom .husky/pre-commit detected — leaving untouched. Append the snippet above so quality:preview runs at commit time.',
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Step 3 — Register the `quality:preview` and `quality:watch` npm scripts
206
+ * in the project's `package.json`. Existing values are preserved
207
+ * unconditionally; this helper only adds missing keys.
208
+ *
209
+ * Returns the per-script outcome so the workflow can surface which scripts
210
+ * were added vs already present.
211
+ */
212
+ export function ensureQualityNpmScripts(ctx) {
213
+ const pkgPath = path.join(ctx.projectRoot, 'package.json');
214
+ const pkg = readJsonIfExists(pkgPath);
215
+ if (!pkg) {
216
+ return { action: 'missing-package-json', path: pkgPath, scripts: {} };
217
+ }
218
+ pkg.scripts = pkg.scripts ?? {};
219
+ const outcomes = {};
220
+ let mutated = false;
221
+ for (const [name, cmd] of Object.entries(QUALITY_NPM_SCRIPTS)) {
222
+ if (typeof pkg.scripts[name] === 'string' && pkg.scripts[name].length > 0) {
223
+ outcomes[name] = 'already-present';
224
+ } else {
225
+ pkg.scripts[name] = cmd;
226
+ outcomes[name] = 'added';
227
+ mutated = true;
228
+ }
229
+ }
230
+ if (mutated) writeJson(pkgPath, pkg);
231
+ return {
232
+ action: mutated ? 'updated' : 'no-change',
233
+ path: pkgPath,
234
+ scripts: outcomes,
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Deep-merge the requested defaults into an object, only setting keys that
240
+ * are absent AND whose intended value diverges from the framework default
241
+ * at that dotted path. The runtime layers `getAgentrcDefaults()`
242
+ * underneath the project config at read time, so a key whose intended
243
+ * value equals the framework default would be written redundantly — and
244
+ * would then be flagged `[REDUNDANT]` by the sync-agentrc helper on the
245
+ * next /agents-update. Default-aware seeding keeps the two helpers from
246
+ * contradicting each other.
247
+ *
248
+ * Returns `{ merged, addedKeys[] }` so the caller can report exactly
249
+ * which keys were seeded. Pure-default writes are reported under
250
+ * `skippedKeys[]` so callers can surface why the seed was a no-op.
251
+ *
252
+ * @param {object} target
253
+ * @param {object} defaults — the values the caller would seed if
254
+ * default-blindness were the policy.
255
+ * @param {object} frameworkDefaults — the framework's resolved defaults
256
+ * at the seed root. Compared to each intended write.
257
+ * @param {string} prefix — dotted path under construction.
258
+ */
259
+ function mergeMissingKeys(
260
+ target,
261
+ defaults,
262
+ frameworkDefaults = {},
263
+ prefix = '',
264
+ ) {
265
+ const addedKeys = [];
266
+ const skippedKeys = [];
267
+ for (const [key, value] of Object.entries(defaults)) {
268
+ const keyPath = prefix ? `${prefix}.${key}` : key;
269
+ const frameworkValue =
270
+ frameworkDefaults && typeof frameworkDefaults === 'object'
271
+ ? frameworkDefaults[key]
272
+ : undefined;
273
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
274
+ if (!target[key] || typeof target[key] !== 'object') {
275
+ target[key] = {};
276
+ }
277
+ const nested = mergeMissingKeys(
278
+ target[key],
279
+ value,
280
+ frameworkValue ?? {},
281
+ keyPath,
282
+ );
283
+ addedKeys.push(...nested.addedKeys);
284
+ skippedKeys.push(...nested.skippedKeys);
285
+ if (
286
+ Object.keys(target[key]).length === 0 &&
287
+ target[key] !== frameworkDefaults?.[key]
288
+ ) {
289
+ delete target[key];
290
+ }
291
+ } else if (target[key] === undefined) {
292
+ if (deepEqual(value, frameworkValue)) {
293
+ skippedKeys.push(keyPath);
294
+ } else {
295
+ target[key] = value;
296
+ addedKeys.push(keyPath);
297
+ }
298
+ }
299
+ }
300
+ return { merged: target, addedKeys, skippedKeys };
301
+ }
302
+
303
+ /**
304
+ * Step 4 — Seed the `delivery.quality.codingGuardrails` and
305
+ * `delivery.quality.autoRefresh` defaults into `.agentrc.json`. Only
306
+ * missing keys are added; existing values are preserved unconditionally
307
+ * (including operator overrides that diverge from the framework defaults).
308
+ *
309
+ * When `.agentrc.json` does not exist the action is `missing-config` and
310
+ * nothing is written — the project must complete its base bootstrap first.
311
+ */
312
+ export function ensureQualityConfigDefaults(ctx) {
313
+ const cfgPath = path.join(ctx.projectRoot, '.agentrc.json');
314
+ const cfg = readJsonIfExists(cfgPath);
315
+ if (!cfg) {
316
+ return {
317
+ action: 'missing-config',
318
+ path: cfgPath,
319
+ addedKeys: [],
320
+ skippedKeys: [],
321
+ };
322
+ }
323
+ const frameworkDefaults = getAgentrcDefaults();
324
+ const frameworkQuality =
325
+ lookupPath(frameworkDefaults, 'delivery.quality').value ?? {};
326
+ const hadDelivery = Object.hasOwn(cfg, 'delivery');
327
+ const hadQuality = hadDelivery && Object.hasOwn(cfg.delivery, 'quality');
328
+ cfg.delivery = cfg.delivery ?? {};
329
+ cfg.delivery.quality = cfg.delivery.quality ?? {};
330
+ const { addedKeys, skippedKeys } = mergeMissingKeys(
331
+ cfg.delivery.quality,
332
+ QUALITY_CONFIG_DEFAULTS,
333
+ frameworkQuality,
334
+ 'delivery.quality',
335
+ );
336
+ if (addedKeys.length > 0) {
337
+ writeJson(cfgPath, cfg);
338
+ } else {
339
+ // No-op path — undo the scaffolding we inserted so the on-disk file
340
+ // and the in-memory snapshot agree (defensive; nothing reads cfg
341
+ // after this).
342
+ if (!hadQuality) delete cfg.delivery.quality;
343
+ if (!hadDelivery) delete cfg.delivery;
344
+ }
345
+ return {
346
+ action: addedKeys.length > 0 ? 'updated' : 'no-change',
347
+ path: cfgPath,
348
+ addedKeys,
349
+ skippedKeys,
350
+ };
351
+ }
352
+
353
+ /**
354
+ * Run all four steps in order. Composable wrapper used by the bootstrap
355
+ * and update workflows. Each step's outcome is returned under its own key
356
+ * so callers can render a per-action summary.
357
+ *
358
+ * @param {object} ctx
359
+ * @param {string} ctx.projectRoot
360
+ * @param {string} [ctx.frameworkRoot]
361
+ * @param {'framework'|'downstream'} [ctx.variant]
362
+ */
363
+ export function applyQualityBootstrap(ctx) {
364
+ return {
365
+ helper: ensureGuardrailsHelper(ctx),
366
+ hook: ensurePreCommitHook(ctx),
367
+ scripts: ensureQualityNpmScripts(ctx),
368
+ config: ensureQualityConfigDefaults(ctx),
369
+ };
370
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * bootstrap/summary — Bootstrap result formatting + summary printing
3
+ *
4
+ * Pure formatting helpers (`format*Summary`) and the `printSummary`
5
+ * presenter extracted from `agents-bootstrap-github.js` (Story #3349).
6
+ * These render the `runBootstrap` result envelope into operator-facing
7
+ * lines; they hold no provider coupling and no orchestration logic.
8
+ */
9
+
10
+ import { Logger } from '../Logger.js';
11
+
12
+ export function formatProjectSummary(project) {
13
+ if (project.scopesMissing) return 'skipped (missing project scope)';
14
+ if (project.created) return `created #${project.projectNumber}`;
15
+ if (project.projectNumber) return `adopted #${project.projectNumber}`;
16
+ return 'skipped';
17
+ }
18
+
19
+ export function formatBranchProtectionSummary(bp) {
20
+ if (!bp) return 'not-run';
21
+ if (bp.status === 'created') return `created (added: ${bp.added.join(', ')})`;
22
+ if (bp.status === 'merged') {
23
+ return bp.added.length
24
+ ? `merged (added: ${bp.added.join(', ')})`
25
+ : 'merged (no changes)';
26
+ }
27
+ if (bp.status === 'skipped') return `skipped (${bp.reason})`;
28
+ if (bp.status === 'failed') return `failed (${bp.reason})`;
29
+ return bp.status;
30
+ }
31
+
32
+ export function formatWorkflowAuditSummary(wa) {
33
+ if (!wa) return 'not-run';
34
+ if (wa.skipped) return `skipped (${wa.reason})`;
35
+ if (wa.action === 'no-conflicts') return 'no conflicting workflows';
36
+ if (wa.action === 'warn-only')
37
+ return `warned (${wa.audit.conflicting.length} conflicting; pass --reap-conflicting-workflows to delete)`;
38
+ if (wa.action === 'reaped') return `reaped ${wa.reaped.length} workflow(s)`;
39
+ return wa.action ?? 'unknown';
40
+ }
41
+
42
+ export function formatMergeMethodsSummary(mm) {
43
+ if (!mm) return 'not-run';
44
+ if (mm.status === 'unchanged') return 'unchanged (already at target stance)';
45
+ if (mm.status === 'patched')
46
+ return `patched (${(mm.patched ?? []).join(', ') || '—'})`;
47
+ if (mm.status === 'skipped') return `skipped (${mm.reason})`;
48
+ if (mm.status === 'failed') return `failed (${mm.reason})`;
49
+ return mm.status;
50
+ }
51
+
52
+ export function printSummary(result) {
53
+ Logger.info('\n=== Bootstrap Summary ===');
54
+ Logger.info(`Labels created: ${result.labels.created.length}`);
55
+ Logger.info(`Labels skipped: ${result.labels.skipped.length}`);
56
+ Logger.info(`Fields created: ${result.fields.created.length}`);
57
+ Logger.info(`Fields skipped: ${result.fields.skipped.length}`);
58
+ Logger.info(`Project: ${formatProjectSummary(result.project)}`);
59
+ Logger.info(`Status field: ${result.statusField.status}`);
60
+ const unavailableSuffix = result.views.unavailable
61
+ ? ' (mutation unavailable)'
62
+ : '';
63
+ Logger.info(
64
+ `Views — created: ${result.views.created.length}, skipped: ${result.views.skipped.length}${unavailableSuffix}`,
65
+ );
66
+ Logger.info(
67
+ `Workflow audit: ${formatWorkflowAuditSummary(result.workflowAudit)}`,
68
+ );
69
+ Logger.info(
70
+ `Branch protection: ${formatBranchProtectionSummary(result.branchProtection)}`,
71
+ );
72
+ Logger.info(
73
+ `Merge methods: ${formatMergeMethodsSummary(result.mergeMethods)}`,
74
+ );
75
+ }
@@ -0,0 +1,256 @@
1
+ /**
2
+ * bootstrap/workflow-audit — audit the GitHub Projects v2 built-in
3
+ * workflows for the project board, classifying each enabled workflow
4
+ * against an allowlist (Story #2845).
5
+ *
6
+ * Motivation:
7
+ * The orchestrator's `ColumnSync` writes the Status column at every
8
+ * `transitionTicketState` call and documents "I own Status" at
9
+ * [`column-sync.js:21-27`]. GitHub Projects v2 ships several built-in
10
+ * workflows that *also* write the Status column as side-effects of
11
+ * issue / PR events. When both are enabled, the bot frequently gets
12
+ * the last write on `agent::done` transitions (PR merged ~2 minutes
13
+ * after the orchestrator's flip), leaving closed Stories stuck at
14
+ * `In Progress` on the board even though the issue is closed and
15
+ * labeled `agent::done`. Reproduced on Story #2813.
16
+ *
17
+ * Surface:
18
+ * - {@link CONFLICTING_WORKFLOWS} / {@link COMPATIBLE_WORKFLOWS} —
19
+ * frozen allowlists keyed by GitHub's built-in workflow `name`
20
+ * field.
21
+ * - {@link auditProjectWorkflows} — pure-ish (one GraphQL read) that
22
+ * classifies the project's currently-enabled workflows and returns
23
+ * a structured envelope.
24
+ * - {@link reapConflictingWorkflows} — opt-in destructive helper
25
+ * that issues `deleteProjectV2Workflow` for every entry in the
26
+ * audit's `conflicting` set. Fails fast on the first mutation
27
+ * error (no partial-reap state).
28
+ *
29
+ * GraphQL surface note:
30
+ * `ProjectV2Workflow` exposes `enabled` as `NON_NULL` but **read-only**
31
+ * — GraphQL ships no `updateProjectV2Workflow` mutation at the time
32
+ * of this Story. The only programmatic action is
33
+ * `deleteProjectV2Workflow`, which is irreversible from the API
34
+ * (the operator must re-create deleted built-ins from the GitHub UI).
35
+ * If GitHub later adds a toggle mutation, swap delete for toggle in
36
+ * {@link reapConflictingWorkflows}.
37
+ */
38
+
39
+ /**
40
+ * Workflows that **must not** be enabled when the orchestrator owns
41
+ * the Status column. Each entry writes Status as a side-effect of an
42
+ * event the orchestrator already handles (close, PR merge, PR link),
43
+ * and the bot's write typically arrives *after* the orchestrator's
44
+ * — clobbering the intended terminal state.
45
+ *
46
+ * Names match GitHub's built-in `ProjectV2Workflow.name` literals.
47
+ */
48
+ export const CONFLICTING_WORKFLOWS = Object.freeze([
49
+ 'Pull request merged',
50
+ 'Pull request linked to issue',
51
+ ]);
52
+
53
+ /**
54
+ * Workflows that are safe to leave on. Either they don't touch the
55
+ * Status column, or they touch it in a way the orchestrator's writes
56
+ * agree with (`Item closed` sets Status to `Done`, which matches
57
+ * `agent::done`).
58
+ *
59
+ * Surfaced informationally in the audit envelope so operators can see
60
+ * what was inspected without re-querying.
61
+ */
62
+ export const COMPATIBLE_WORKFLOWS = Object.freeze([
63
+ 'Item closed',
64
+ 'Item added to project',
65
+ 'Auto-add to project',
66
+ 'Auto-add sub-issues to project',
67
+ 'Auto-close issue',
68
+ ]);
69
+
70
+ const CONFLICTING_SET = new Set(CONFLICTING_WORKFLOWS);
71
+ const COMPATIBLE_SET = new Set(COMPATIBLE_WORKFLOWS);
72
+
73
+ const LIST_WORKFLOWS_QUERY = `
74
+ query($projectId: ID!) {
75
+ node(id: $projectId) {
76
+ ... on ProjectV2 {
77
+ workflows(first: 50) {
78
+ nodes { id name number enabled }
79
+ }
80
+ }
81
+ }
82
+ }`;
83
+
84
+ const DELETE_WORKFLOW_MUTATION = `
85
+ mutation($workflowId: ID!) {
86
+ deleteProjectV2Workflow(input: { workflowId: $workflowId }) {
87
+ projectV2 { id }
88
+ }
89
+ }`;
90
+
91
+ /**
92
+ * Classify a single workflow row against the allowlists.
93
+ *
94
+ * Pure helper — exported for test pinning.
95
+ *
96
+ * @param {{ name: string, enabled: boolean }} workflow
97
+ * @returns {'conflicting'|'compatible'|'unknown'|'disabled-conflicting'|'disabled-other'}
98
+ */
99
+ export function classifyWorkflow(workflow) {
100
+ const name = workflow?.name ?? '';
101
+ const enabled = workflow?.enabled === true;
102
+ if (CONFLICTING_SET.has(name)) {
103
+ return enabled ? 'conflicting' : 'disabled-conflicting';
104
+ }
105
+ if (COMPATIBLE_SET.has(name)) {
106
+ return 'compatible';
107
+ }
108
+ return enabled ? 'unknown' : 'disabled-other';
109
+ }
110
+
111
+ /**
112
+ * Query the project's built-in workflows and classify each one. Returns
113
+ * a structured envelope the bootstrap step can render and the reap
114
+ * helper can act on.
115
+ *
116
+ * @param {{
117
+ * provider: { graphql: Function },
118
+ * projectId: string,
119
+ * }} args
120
+ * @returns {Promise<{
121
+ * projectId: string,
122
+ * total: number,
123
+ * conflicting: Array<{ id: string, name: string, number: number }>,
124
+ * compatible: Array<{ id: string, name: string, number: number }>,
125
+ * unknown: Array<{ id: string, name: string, number: number }>,
126
+ * disabled: Array<{ id: string, name: string, number: number }>,
127
+ * }>}
128
+ */
129
+ export async function auditProjectWorkflows(args) {
130
+ const { provider, projectId } = args ?? {};
131
+ if (!provider || typeof provider.graphql !== 'function') {
132
+ throw new TypeError(
133
+ 'auditProjectWorkflows requires a provider with graphql',
134
+ );
135
+ }
136
+ if (typeof projectId !== 'string' || projectId.length === 0) {
137
+ throw new TypeError('auditProjectWorkflows requires a non-empty projectId');
138
+ }
139
+ const data = await provider.graphql(LIST_WORKFLOWS_QUERY, { projectId });
140
+ const nodes = data?.node?.workflows?.nodes ?? [];
141
+ const conflicting = [];
142
+ const compatible = [];
143
+ const unknown = [];
144
+ const disabled = [];
145
+ for (const node of nodes) {
146
+ const row = { id: node.id, name: node.name, number: node.number };
147
+ const klass = classifyWorkflow(node);
148
+ if (klass === 'conflicting') conflicting.push(row);
149
+ else if (klass === 'compatible') compatible.push(row);
150
+ else if (klass === 'unknown') unknown.push(row);
151
+ else disabled.push(row);
152
+ }
153
+ return {
154
+ projectId,
155
+ total: nodes.length,
156
+ conflicting,
157
+ compatible,
158
+ unknown,
159
+ disabled,
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Delete every workflow in the audit's `conflicting` set. Fails fast on
165
+ * the first mutation error — leaves the remaining workflows untouched
166
+ * rather than producing a partially-reaped board, because the operator
167
+ * cannot easily tell which workflows were deleted versus which were
168
+ * preserved when looking at the post-failure board state.
169
+ *
170
+ * Returns the per-workflow outcome so callers can log a deterministic
171
+ * summary even on partial success (the failure path will throw, but the
172
+ * happy path returns the full ordered list for printing).
173
+ *
174
+ * @param {{
175
+ * provider: { graphql: Function },
176
+ * audit: ReturnType<typeof auditProjectWorkflows> extends Promise<infer R> ? R : never,
177
+ * }} args
178
+ * @returns {Promise<{ reaped: Array<{ id: string, name: string }> }>}
179
+ */
180
+ export async function reapConflictingWorkflows(args) {
181
+ const { provider, audit } = args ?? {};
182
+ if (!provider || typeof provider.graphql !== 'function') {
183
+ throw new TypeError(
184
+ 'reapConflictingWorkflows requires a provider with graphql',
185
+ );
186
+ }
187
+ if (!audit || !Array.isArray(audit.conflicting)) {
188
+ throw new TypeError(
189
+ 'reapConflictingWorkflows requires an audit envelope with .conflicting[]',
190
+ );
191
+ }
192
+ const reaped = [];
193
+ for (const wf of audit.conflicting) {
194
+ try {
195
+ await provider.graphql(DELETE_WORKFLOW_MUTATION, { workflowId: wf.id });
196
+ reaped.push({ id: wf.id, name: wf.name });
197
+ } catch (err) {
198
+ throw new Error(
199
+ `[workflow-audit] Failed to delete workflow "${wf.name}" (id=${wf.id}): ${err?.message ?? err}. ` +
200
+ `${reaped.length} workflow(s) were already deleted before this failure: ${
201
+ reaped.map((r) => r.name).join(', ') || '(none)'
202
+ }.`,
203
+ );
204
+ }
205
+ }
206
+ return { reaped };
207
+ }
208
+
209
+ /**
210
+ * Resolve a Project v2 node id from a project number against the viewer
211
+ * scope. Used by the bootstrap CLI to convert the resolver's
212
+ * `projectNumber` into the node id required by
213
+ * {@link auditProjectWorkflows}. Returns `null` when the viewer cannot
214
+ * see the project (e.g. missing scope, project not under viewer) so the
215
+ * caller can degrade gracefully.
216
+ *
217
+ * @param {{ provider: { graphql: Function }, projectNumber: number }} args
218
+ * @returns {Promise<string|null>}
219
+ */
220
+ export async function resolveProjectIdByNumber(args) {
221
+ const { provider, projectNumber } = args ?? {};
222
+ if (!provider || typeof provider.graphql !== 'function') {
223
+ throw new TypeError(
224
+ 'resolveProjectIdByNumber requires a provider with graphql',
225
+ );
226
+ }
227
+ if (!Number.isInteger(projectNumber) || projectNumber <= 0) {
228
+ throw new TypeError(
229
+ 'resolveProjectIdByNumber requires a positive integer projectNumber',
230
+ );
231
+ }
232
+ try {
233
+ const data = await provider.graphql(
234
+ `query($n: Int!) { viewer { projectV2(number: $n) { id } } }`,
235
+ { n: projectNumber },
236
+ );
237
+ return data?.viewer?.projectV2?.id ?? null;
238
+ } catch {
239
+ return null;
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Render a human-readable summary line for the audit. Pure — exported
245
+ * so the bootstrap CLI and tests share the same formatting.
246
+ *
247
+ * @param {Awaited<ReturnType<typeof auditProjectWorkflows>>} audit
248
+ * @returns {string}
249
+ */
250
+ export function formatAuditSummary(audit) {
251
+ const c = audit.conflicting.length;
252
+ const ok = audit.compatible.length;
253
+ const u = audit.unknown.length;
254
+ const d = audit.disabled.length;
255
+ return `workflows: ${audit.total} scanned — ${c} conflicting, ${ok} compatible, ${u} unknown, ${d} disabled`;
256
+ }