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,222 @@
1
+ /**
2
+ * bootstrap/branch-protection
3
+ *
4
+ * Consumer-parity branch-protection writer. The bootstrap applies a
5
+ * CI-gates-only stance every project in the framework inherits:
6
+ *
7
+ * - `enforce_admins: true` — admins do not bypass the prGate suite.
8
+ * - `required_pull_request_reviews.required_approving_review_count: 0` —
9
+ * CI is the gate; the operator monitors and iterates the open PR
10
+ * to green via `/epic-deliver`'s Phase 7 watch loop.
11
+ *
12
+ * Behaviour rules
13
+ * ---------------
14
+ * Fresh rule (no existing protection):
15
+ * The framework writes the full opinionated payload directly. No HITL
16
+ * prompt — there is nothing to diff against.
17
+ *
18
+ * Existing rule that already matches the target stance:
19
+ * Pure-additive append of any missing prGate.checks contexts. No HITL
20
+ * prompt (preserves the today-non-interactive contract for additive
21
+ * changes).
22
+ *
23
+ * Existing rule that *diverges* on a behavior-shifting field
24
+ * (enforce_admins flip, approval-count change, strict-checks flip, or any
25
+ * required-check context dropped):
26
+ * Routes the proposed payload through `hitlConfirm`. On rejection or
27
+ * non-TTY abort, the call is a no-op and we return
28
+ * `{ status: 'skipped', reason: 'hitl-declined' }`. On approval, we
29
+ * apply the diverging payload.
30
+ *
31
+ * Errors (insufficient scopes, repo permission denied, etc.) are logged
32
+ * and surfaced as `{ status: 'failed' }` — the rest of the bootstrap is
33
+ * not aborted. Matches `agents-bootstrap-github.js` failure handling so
34
+ * the wrapper stays predictable.
35
+ */
36
+
37
+ const TARGET_ENFORCE_ADMINS = true;
38
+ const TARGET_APPROVAL_COUNT = 0;
39
+
40
+ /**
41
+ * Detect whether `current` (the GitHub API's `raw` protection payload)
42
+ * diverges from the target stance on any behavior-shifting field. The
43
+ * return value is a structured diff suitable for `hitlConfirm` so the
44
+ * operator sees exactly what would flip.
45
+ */
46
+ export function diffProtection(current, targetContexts) {
47
+ if (!current) return null; // create-from-scratch path; no diff needed.
48
+
49
+ const diff = {};
50
+ const liveEnforceAdmins = current?.enforce_admins?.enabled ?? false;
51
+ if (liveEnforceAdmins !== TARGET_ENFORCE_ADMINS) {
52
+ diff.enforceAdmins = {
53
+ current: liveEnforceAdmins,
54
+ proposed: TARGET_ENFORCE_ADMINS,
55
+ };
56
+ }
57
+
58
+ const liveReviews = current?.required_pull_request_reviews ?? null;
59
+ // Live `null` means "PR reviews not configured at all". We *do* want to
60
+ // promote the explicit zero-approval policy in that case, so the diff
61
+ // reports it as a flip from null → { required_approving_review_count: 0 }.
62
+ // An explicit zero-count rule blocks any future operator drift back to
63
+ // 1+, which would re-introduce the approval-theater dependency the
64
+ // framework deliberately stripped out.
65
+ const liveApprovalCount = liveReviews?.required_approving_review_count;
66
+ if (liveApprovalCount !== TARGET_APPROVAL_COUNT) {
67
+ diff.approvingReviewCount = {
68
+ current: liveApprovalCount ?? null,
69
+ proposed: TARGET_APPROVAL_COUNT,
70
+ };
71
+ }
72
+
73
+ const liveContexts = current?.required_status_checks?.contexts ?? [];
74
+ const dropped = liveContexts.filter((c) => !targetContexts.includes(c));
75
+ // We never *drop* operator contexts — the writer is additive on that
76
+ // axis. So a dropped-on-target list is informational only and never
77
+ // makes us route through HITL. Only enforce-admins / approval-count
78
+ // shifts trigger the gate.
79
+ if (dropped.length > 0) {
80
+ diff.preservedContexts = dropped;
81
+ }
82
+
83
+ return Object.keys(diff).length > 0 ? diff : null;
84
+ }
85
+
86
+ function isBehaviorShifting(diff) {
87
+ if (!diff) return false;
88
+ return (
89
+ Object.hasOwn(diff, 'enforceAdmins') ||
90
+ Object.hasOwn(diff, 'approvingReviewCount')
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Apply the framework's branch-protection stance to `baseBranch`.
96
+ *
97
+ * @param {object} args
98
+ * @param {object} args.provider - Ticketing provider exposing
99
+ * `getBranchProtection(branch)` and `setBranchProtection(branch, opts)`.
100
+ * @param {object} args.settings - The resolved settings bag. Carries
101
+ * `baseBranch` (default `main`) and `github.branchProtection.{enforce,
102
+ * requiredChecks}` post-reshape.
103
+ * @param {(args:{summary:string, current:object|null, proposed:object})=>Promise<boolean>}
104
+ * [args.hitlConfirm] - HITL gate. Defaults to "abort on diverge"
105
+ * (returns false) when omitted — matching the non-TTY contract.
106
+ * @param {(msg:string)=>void} [args.log] - Logger sink. Defaults to a no-op.
107
+ */
108
+ export async function applyBranchProtection({
109
+ provider,
110
+ settings,
111
+ hitlConfirm,
112
+ log = () => {},
113
+ }) {
114
+ const baseBranch = settings?.baseBranch ?? 'main';
115
+ // Post-reshape: branch protection lives under `github.branchProtection`.
116
+ // The legacy `quality.prGate` location is gone from the schema; reading
117
+ // it here is a transitional fallback only.
118
+ const branchProtection =
119
+ settings?.github?.branchProtection ?? settings?.quality?.prGate ?? null;
120
+ const enforce =
121
+ branchProtection?.enforce ??
122
+ branchProtection?.enforceBranchProtection ??
123
+ true;
124
+ const requiredChecks =
125
+ branchProtection?.requiredChecks ?? branchProtection?.checks ?? [];
126
+
127
+ if (enforce === false) {
128
+ log(
129
+ `[bootstrap] Branch protection on '${baseBranch}': skipped (github.branchProtection.enforce=false).`,
130
+ );
131
+ return { status: 'skipped', reason: 'opt-out' };
132
+ }
133
+
134
+ const checkNames = requiredChecks
135
+ .map((c) => c?.name)
136
+ .filter((n) => typeof n === 'string' && n.length > 0);
137
+ if (checkNames.length === 0) {
138
+ log(
139
+ `[bootstrap] Branch protection on '${baseBranch}': skipped (no github.branchProtection.requiredChecks configured).`,
140
+ );
141
+ return { status: 'skipped', reason: 'no-checks' };
142
+ }
143
+
144
+ // Story #2018 (Bug 3): on a fresh-empty repo with no commits yet, the
145
+ // base branch hasn't been pushed and the protection PUT would 404 with
146
+ // a confusing transport error. Probe for existence first so operators
147
+ // get a clear "no-base-branch" skip rather than discovering the
148
+ // `enforce: false` opt-out by reading the failure message.
149
+ if (typeof provider.branchExists === 'function') {
150
+ let exists = true;
151
+ try {
152
+ exists = await provider.branchExists(baseBranch);
153
+ } catch (err) {
154
+ log(
155
+ `[bootstrap] Branch protection on '${baseBranch}': existence probe failed — ${err.message}. Proceeding with the write attempt.`,
156
+ );
157
+ }
158
+ if (!exists) {
159
+ log(
160
+ `[bootstrap] Branch protection on '${baseBranch}': skipped (base branch does not exist on the remote — push an initial commit first).`,
161
+ );
162
+ return { status: 'skipped', reason: 'no-base-branch' };
163
+ }
164
+ }
165
+
166
+ let current = null;
167
+ try {
168
+ const probe = await provider.getBranchProtection(baseBranch);
169
+ current = probe?.enabled ? (probe.raw ?? null) : null;
170
+ } catch (err) {
171
+ log(
172
+ `[bootstrap] Branch protection on '${baseBranch}': read failed — ${err.message}. Proceeding as if no rule exists.`,
173
+ );
174
+ }
175
+
176
+ const diff = diffProtection(current, checkNames);
177
+ if (isBehaviorShifting(diff)) {
178
+ const approved =
179
+ typeof hitlConfirm === 'function'
180
+ ? await hitlConfirm({
181
+ summary: `Branch protection on '${baseBranch}' diverges from the framework's CI-gates-only stance (enforce_admins=true, required_approving_review_count=0).`,
182
+ current: {
183
+ enforce_admins: current?.enforce_admins?.enabled ?? false,
184
+ required_approving_review_count:
185
+ current?.required_pull_request_reviews
186
+ ?.required_approving_review_count ?? null,
187
+ },
188
+ proposed: {
189
+ enforce_admins: TARGET_ENFORCE_ADMINS,
190
+ required_approving_review_count: TARGET_APPROVAL_COUNT,
191
+ },
192
+ })
193
+ : false;
194
+ if (!approved) {
195
+ log(
196
+ `[bootstrap] Branch protection on '${baseBranch}': diverges from framework stance; HITL declined / non-TTY — leaving the operator's rule untouched.`,
197
+ );
198
+ return { status: 'skipped', reason: 'hitl-declined', diff };
199
+ }
200
+ }
201
+
202
+ try {
203
+ const result = await provider.setBranchProtection(baseBranch, {
204
+ contexts: checkNames,
205
+ enforceAdmins: TARGET_ENFORCE_ADMINS,
206
+ requiredApprovingReviewCount: TARGET_APPROVAL_COUNT,
207
+ });
208
+ const verb = result.created ? 'Created' : 'Updated';
209
+ const addedSuffix = result.added.length
210
+ ? ` (added: ${result.added.join(', ')})`
211
+ : ' (all required checks already present)';
212
+ log(
213
+ `[bootstrap] Branch protection on '${baseBranch}': ${verb} rule${addedSuffix}.`,
214
+ );
215
+ return { status: result.created ? 'created' : 'merged', ...result };
216
+ } catch (err) {
217
+ log(
218
+ `[bootstrap] Branch protection on '${baseBranch}': failed — ${err.message}. Proceeding without it.`,
219
+ );
220
+ return { status: 'failed', reason: err.message };
221
+ }
222
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * bootstrap/ci-workflow-template — Story #1401 (Epic #1386)
3
+ *
4
+ * Renders the stabilized-quality-gates CI workflow YAML that
5
+ * `/agents-bootstrap-github` writes (or refreshes) on a downstream project's
6
+ * `.github/workflows/ci.yml`. Two design rules drive the shape:
7
+ *
8
+ * 1. **Lean on the diff-scoped default.** Story #1394 flipped both gate
9
+ * CLIs (`check-maintainability.js`, `check-crap.js`) to default
10
+ * `--changed-since=main`. The template no longer passes `--changed-since`
11
+ * explicitly on the per-PR job — the default already produces the right
12
+ * diff scope and an explicit re-statement risks drifting from the
13
+ * framework default at the next bump. The push-to-main job still passes
14
+ * `--full-scope` so a self-diff doesn't degrade to "no files in diff".
15
+ *
16
+ * 2. **Pass `--epic-ref` where the firing site is Epic-aware.** Inside
17
+ * `/story-deliver` the close-validation chain already threads
18
+ * `--epic-ref epic/<id>`; on CI the equivalent surface is the PR's
19
+ * base branch. The template wires `--epic-ref ${EPIC_REF}` through an
20
+ * env var the workflow computes from `github.head_ref` (story-N
21
+ * branches name their Epic in the PR title or via the dispatch
22
+ * manifest). When `EPIC_REF` is empty, both gates fall through to the
23
+ * `main`-tracked baseline — so the env-var expansion is always safe.
24
+ *
25
+ * The renderer is a pure string template so the integration test can assert
26
+ * on its exact shape without instantiating a YAML parser.
27
+ *
28
+ * @module bootstrap/ci-workflow-template
29
+ */
30
+
31
+ /**
32
+ * @typedef {object} CiTemplateOptions
33
+ * @property {string} [nodeVersion='22'] - Node major to install via setup-node.
34
+ * @property {string} [baseRef='main'] - Default base ref the gate CLIs diff
35
+ * against. Surfaces as the workflow's `BASE_REF` env so the template stays
36
+ * tunable per consumer.
37
+ * @property {boolean} [includeCrap=true] - Whether to render the CRAP step.
38
+ * Some downstream projects keep CRAP off until they have coverage wired.
39
+ */
40
+
41
+ /**
42
+ * Render the CI workflow YAML body. The output is deterministic and safe to
43
+ * write byte-for-byte over an existing template — the bootstrap caller is
44
+ * responsible for diff-aware merging when an operator has hand-edited
45
+ * `ci.yml`.
46
+ *
47
+ * @param {CiTemplateOptions} [opts]
48
+ * @returns {string}
49
+ */
50
+ export function renderCiWorkflow(opts = {}) {
51
+ const nodeVersion = opts.nodeVersion ?? '22';
52
+ const baseRef = opts.baseRef ?? 'main';
53
+ const includeCrap = opts.includeCrap !== false;
54
+
55
+ const crapBlock = includeCrap
56
+ ? `
57
+ - name: CRAP Check
58
+ # Diff-scoped via the framework default (Story #1394 flipped
59
+ # --changed-since to '${baseRef}'). On PRs we let the default win;
60
+ # on push-to-main we pass --full-scope so a self-diff doesn't
61
+ # collapse to an empty file set. EPIC_REF is set when the head ref
62
+ # points at a story branch under an Epic — the gate then reads the
63
+ # per-Epic baseline snapshot via baseline-loader.readBaselineAtRef.
64
+ env:
65
+ EPIC_REF: \${{ env.EPIC_REF }}
66
+ run: |
67
+ mkdir -p temp
68
+ if [[ "\${{ github.event_name }}" == "pull_request" ]]; then
69
+ if [[ -n "\${EPIC_REF}" ]]; then
70
+ npm run crap:check -- --epic-ref "\${EPIC_REF}" --json temp/crap-report.json
71
+ else
72
+ npm run crap:check -- --json temp/crap-report.json
73
+ fi
74
+ else
75
+ npm run crap:check -- --full-scope --json temp/crap-report.json
76
+ fi
77
+
78
+ - name: Upload CRAP Report
79
+ uses: actions/upload-artifact@v4
80
+ if: always()
81
+ with:
82
+ name: crap-report
83
+ path: temp/crap-report.json
84
+ `
85
+ : '';
86
+
87
+ return `# Generated by agents-bootstrap-github (Epic #1386 / Story #1401).
88
+ # Re-run /agents-bootstrap-github to refresh this file. Hand edits are
89
+ # preserved by the bootstrap helper when it detects operator changes —
90
+ # inspect the diff before accepting an overwrite.
91
+ name: CI
92
+
93
+ on:
94
+ push:
95
+ branches: [${baseRef}]
96
+ pull_request:
97
+ branches: [${baseRef}]
98
+ types: [opened, synchronize, reopened]
99
+ workflow_dispatch:
100
+
101
+ concurrency:
102
+ group: \${{ github.workflow }}-\${{ github.ref }}
103
+ cancel-in-progress: true
104
+
105
+ jobs:
106
+ validate:
107
+ name: Validate and Test
108
+ runs-on: ubuntu-latest
109
+ permissions:
110
+ contents: read
111
+ env:
112
+ # Story #1120: when the PR head ref names an Epic story branch
113
+ # (story-N or story/epic-<id>/<n>), the gate CLIs read the canonical
114
+ # main baseline at the Epic branch HEAD via --epic-ref (git show).
115
+ # Empty when the head ref is not an Epic story branch — both gates
116
+ # fall through to the working-tree baseline, so the env-var
117
+ # expansion is always safe. Per-epic ratchet snapshots themselves
118
+ # live under temp/epic/<id>/baselines/ (Story #1467) — ephemeral
119
+ # scratch state, never read by this CI gate.
120
+ EPIC_REF: \${{ github.head_ref && contains(github.head_ref, 'story') && format('epic/{0}', github.event.pull_request.base.ref) || '' }}
121
+ BASE_REF: ${baseRef}
122
+ steps:
123
+ - name: Checkout Code
124
+ uses: actions/checkout@v4
125
+ with:
126
+ fetch-depth: 0
127
+
128
+ - name: Setup Node.js
129
+ uses: actions/setup-node@v4
130
+ with:
131
+ node-version: '${nodeVersion}'
132
+ cache: 'npm'
133
+
134
+ - name: Install Dependencies
135
+ run: npm ci --ignore-scripts
136
+
137
+ - name: Lint and Format
138
+ run: |
139
+ npm run lint
140
+ npm run format:check
141
+
142
+ - name: Maintainability Check
143
+ # Story #1394 (Epic #1386): the gate CLI defaults --changed-since to
144
+ # the project's BASE_REF, so PRs no longer pass --changed-since
145
+ # explicitly. push-to-${baseRef} runs with --full-scope so the
146
+ # diff-scoped default doesn't degrade to a self-diff (= empty file
147
+ # set). EPIC_REF carries the per-Epic snapshot when present.
148
+ env:
149
+ EPIC_REF: \${{ env.EPIC_REF }}
150
+ run: |
151
+ if [[ "\${{ github.event_name }}" == "pull_request" ]]; then
152
+ if [[ -n "\${EPIC_REF}" ]]; then
153
+ npm run maintainability:check -- --epic-ref "\${EPIC_REF}"
154
+ else
155
+ npm run maintainability:check
156
+ fi
157
+ else
158
+ npm run maintainability:check -- --full-scope
159
+ fi
160
+
161
+ - name: Run Tests
162
+ run: npm test
163
+ ${crapBlock}`;
164
+ }
165
+
166
+ /**
167
+ * Default workflow filename emitted by the bootstrap. Surfaced as a constant
168
+ * so the integration test can assert the bootstrap writes to the canonical
169
+ * path without re-deriving it.
170
+ */
171
+ export const CI_WORKFLOW_RELATIVE_PATH = '.github/workflows/ci.yml';
@@ -0,0 +1,146 @@
1
+ /**
2
+ * bootstrap/commit-push — end-of-bootstrap "commit + push the wiring" offer
3
+ * (Story #3899, Finding A.6).
4
+ *
5
+ * After a successful bootstrap the consumer's working tree carries the
6
+ * framework wiring (`.agents/` tree, `.agentrc.json`, `CLAUDE.md`,
7
+ * `.claude/settings.json`, `.gitignore`, `package.json`, `.husky/`). Nothing
8
+ * told the operator to commit and push it — yet Story delivery runs in git
9
+ * worktrees that check out **tracked files only**, so an uncommitted
10
+ * `.agents/` means no scripts exist inside any worktree and every Story
11
+ * sub-agent breaks. This module offers that commit + push at the end of the
12
+ * run, and prints the exact manual commands when the offer is declined or the
13
+ * run is non-interactive.
14
+ *
15
+ * Security: the stage step uses an explicit **allowlist** of bootstrap-written
16
+ * paths (`git add -- <path>`), never `git add -A`, and explicitly refuses to
17
+ * stage known secret files (`.env`, `.mcp.json`, `.agentrc.local.json`). This
18
+ * keeps the commit safe regardless of whether the secret-safe `.gitignore`
19
+ * Story (#3894) has landed — secrets are never staged even when un-ignored.
20
+ *
21
+ * Every git-touching helper takes an injectable `runGit` seam so the logic is
22
+ * unit-testable without spawning a real `git`. The seam contract mirrors
23
+ * `bootstrap.js#runGit`: `({ ok, status, stdout, stderr })`.
24
+ *
25
+ * @module bootstrap/commit-push
26
+ */
27
+
28
+ import fs from 'node:fs';
29
+ import path from 'node:path';
30
+
31
+ /**
32
+ * The bootstrap-written, version-controllable paths the commit offer stages.
33
+ * Project-root-relative POSIX paths. Mirrors the file targets the bootstrap
34
+ * pipeline writes (see `manifest.js` + `project-bootstrap.js`) plus the
35
+ * materialized `.agents/` tree and `.husky/` quality hook. `.claude/commands/`
36
+ * is intentionally absent — it is generated and gitignored.
37
+ *
38
+ * @type {readonly string[]}
39
+ */
40
+ export const BOOTSTRAP_COMMIT_PATHS = Object.freeze([
41
+ '.agents',
42
+ '.agentrc.json',
43
+ 'CLAUDE.md',
44
+ '.claude/settings.json',
45
+ '.gitignore',
46
+ 'package.json',
47
+ 'package-lock.json',
48
+ '.husky',
49
+ ]);
50
+
51
+ /**
52
+ * Paths that MUST NEVER be staged by the commit offer, even when they are not
53
+ * (yet) gitignored. These carry secrets or per-operator local overrides. This
54
+ * is the defense-in-depth that lets the offer run safely before the
55
+ * secret-safe `.gitignore` Story (#3894) lands.
56
+ *
57
+ * @type {ReadonlySet<string>}
58
+ */
59
+ export const NEVER_STAGE_PATHS = Object.freeze(
60
+ new Set([
61
+ '.env',
62
+ '.env.local',
63
+ '.mcp.json',
64
+ '.agentrc.local.json',
65
+ '.agents/instructions.local.md',
66
+ ]),
67
+ );
68
+
69
+ /**
70
+ * The conventional commit subject the offer uses for the wiring commit.
71
+ *
72
+ * @type {string}
73
+ */
74
+ export const COMMIT_SUBJECT = 'chore: wire up Mandrel agent framework';
75
+
76
+ /**
77
+ * Resolve the subset of {@link BOOTSTRAP_COMMIT_PATHS} that actually exist on
78
+ * disk and are not in {@link NEVER_STAGE_PATHS}. Pure (filesystem read only):
79
+ * the secret-exclusion is applied here so a never-stage path is dropped before
80
+ * it ever reaches `git add`.
81
+ *
82
+ * @param {string} projectRoot
83
+ * @param {typeof fs} [fsImpl]
84
+ * @returns {string[]} project-root-relative paths safe to stage
85
+ */
86
+ export function resolveStagePaths(projectRoot, fsImpl = fs) {
87
+ return BOOTSTRAP_COMMIT_PATHS.filter((rel) => {
88
+ if (NEVER_STAGE_PATHS.has(rel)) return false;
89
+ return fsImpl.existsSync(path.join(projectRoot, rel));
90
+ });
91
+ }
92
+
93
+ /**
94
+ * Build the exact manual commands the operator should run to commit and push
95
+ * the wiring themselves. Printed when the offer is declined or the run is
96
+ * non-interactive (`--assume-yes`). The `git add` line stages the resolved
97
+ * allowlist only — never `git add -A` — so copy-pasting it cannot stage a
98
+ * secret file.
99
+ *
100
+ * @param {object} args
101
+ * @param {string[]} args.stagePaths — resolved, secret-free paths to stage.
102
+ * @param {string} args.baseBranch
103
+ * @returns {string} a multi-line, copy-pasteable command block
104
+ */
105
+ export function buildManualInstructions({ stagePaths, baseBranch }) {
106
+ const addArgs = stagePaths.length > 0 ? stagePaths.join(' ') : '.';
107
+ return [
108
+ 'To commit and push the Mandrel setup yourself, run:',
109
+ '',
110
+ ` git add ${addArgs}`,
111
+ ` git commit -m "${COMMIT_SUBJECT}"`,
112
+ ` git push -u origin ${baseBranch}`,
113
+ '',
114
+ 'Story delivery runs in git worktrees that check out tracked files only,',
115
+ 'so the .agents/ wiring MUST be committed before any /story-deliver or',
116
+ '/epic-deliver run — otherwise the worktree has no scripts and breaks.',
117
+ ].join('\n');
118
+ }
119
+
120
+ /**
121
+ * Stage the resolved allowlist via `git add -- <paths>`. No-op (returns
122
+ * `{ ok: true, staged: [] }`) when nothing resolves. Returns the git result on
123
+ * failure so the caller can surface it.
124
+ *
125
+ * @param {object} args
126
+ * @param {string} args.projectRoot
127
+ * @param {(args: string[], cwd: string) => { ok: boolean, status?: number,
128
+ * stdout?: string, stderr?: string }} args.runGit
129
+ * @param {typeof fs} [args.fsImpl]
130
+ * @returns {{ ok: boolean, staged: string[], error?: string }}
131
+ */
132
+ export function stageBootstrapFiles({ projectRoot, runGit, fsImpl = fs }) {
133
+ const stagePaths = resolveStagePaths(projectRoot, fsImpl);
134
+ if (stagePaths.length === 0) {
135
+ return { ok: true, staged: [] };
136
+ }
137
+ const result = runGit(['add', '--', ...stagePaths], projectRoot);
138
+ if (!result.ok) {
139
+ return {
140
+ ok: false,
141
+ staged: [],
142
+ error: result.stderr || 'git add failed',
143
+ };
144
+ }
145
+ return { ok: true, staged: stagePaths };
146
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * bootstrap/gh-list — `gh`-backed list providers for live pickers.
3
+ *
4
+ * Provides the selection substrate for interactive pickers: thin wrappers
5
+ * over `gh repo list` / `gh project list` that shell out via the same
6
+ * `spawnSync('gh', …)` convention used elsewhere in the bootstrap libs
7
+ * (see `gh-preflight.js`). Both providers return a plain array of string
8
+ * values and degrade to an **empty array on any non-zero exit** (or spawn
9
+ * error), so a missing scope, an unauthenticated host, or a `gh` that is
10
+ * too old never throws here — the caller (the `resolveFromPicker` resolver
11
+ * in `prompt.js`) treats an empty list as "no picker available" and falls
12
+ * through to manual entry.
13
+ *
14
+ * The `runner` seam mirrors `gh-preflight.js`: it defaults to a real
15
+ * `spawnSync('gh', …)` but lets tests inject a stub returning the canonical
16
+ * `{ status, stdout, stderr, error }` shape without spawning a child.
17
+ */
18
+
19
+ import { spawnSync } from 'node:child_process';
20
+
21
+ /**
22
+ * Default runner: synchronously execs `gh <args>` and returns the canonical
23
+ * `{ status, stdout, stderr, error }` shape. Extracted so tests can inject a
24
+ * stub without spawning a real child process.
25
+ *
26
+ * @param {string[]} args
27
+ * @returns {{ status: number|null, stdout: string, stderr: string,
28
+ * error?: NodeJS.ErrnoException }}
29
+ */
30
+ function defaultGhRunner(args) {
31
+ const result = spawnSync('gh', args, { encoding: 'utf8' });
32
+ return {
33
+ status: result.status,
34
+ stdout: typeof result.stdout === 'string' ? result.stdout : '',
35
+ stderr: typeof result.stderr === 'string' ? result.stderr : '',
36
+ error: result.error,
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Parse newline-delimited JSON-array stdout into a flat list of strings via
42
+ * the supplied `mapItem`. Returns `[]` for empty/whitespace stdout or any
43
+ * shape that does not parse to an array. Non-string mapped values are
44
+ * dropped so the picker only ever renders selectable strings.
45
+ *
46
+ * @param {string} stdout
47
+ * @param {(item: unknown) => unknown} mapItem
48
+ * @returns {string[]}
49
+ */
50
+ function parseJsonList(stdout, mapItem) {
51
+ const trimmed = (stdout || '').trim();
52
+ if (trimmed.length === 0) return [];
53
+ let parsed;
54
+ try {
55
+ parsed = JSON.parse(trimmed);
56
+ } catch {
57
+ return [];
58
+ }
59
+ if (!Array.isArray(parsed)) return [];
60
+ return parsed
61
+ .map(mapItem)
62
+ .filter((value) => typeof value === 'string' && value.length > 0);
63
+ }
64
+
65
+ /**
66
+ * List repositories for an owner via `gh repo list <owner>`. Returns the
67
+ * `owner/name` slug for each repo, or `[]` on any non-zero exit / spawn
68
+ * error / missing owner.
69
+ *
70
+ * @param {{ owner?: string, runner?: (args: string[]) => {
71
+ * status: number|null, stdout: string, stderr: string,
72
+ * error?: NodeJS.ErrnoException
73
+ * } }} [opts]
74
+ * @returns {string[]}
75
+ */
76
+ export function listRepos(opts = {}) {
77
+ const { owner, runner = defaultGhRunner } = opts;
78
+ if (typeof owner !== 'string' || owner.length === 0) return [];
79
+ const result = runner([
80
+ 'repo',
81
+ 'list',
82
+ owner,
83
+ '--json',
84
+ 'nameWithOwner',
85
+ '--limit',
86
+ '100',
87
+ ]);
88
+ if (result.error || result.status !== 0) return [];
89
+ return parseJsonList(result.stdout, (item) =>
90
+ item && typeof item === 'object' ? item.nameWithOwner : undefined,
91
+ );
92
+ }
93
+
94
+ /**
95
+ * List projects (Projects v2) for an owner via `gh project list --owner
96
+ * <owner>`. Returns one `{ label, value }` choice per project — `label` is
97
+ * the human-readable title (with the number appended) and `value` is the
98
+ * numeric Projects V2 number as a string — or `[]` on any non-zero exit /
99
+ * spawn error / missing owner.
100
+ *
101
+ * @param {{ owner?: string, runner?: (args: string[]) => {
102
+ * status: number|null, stdout: string, stderr: string,
103
+ * error?: NodeJS.ErrnoException
104
+ * } }} [opts]
105
+ * @returns {{ label: string, value: string }[]}
106
+ */
107
+ export function listProjects(opts = {}) {
108
+ const { owner, runner = defaultGhRunner } = opts;
109
+ if (typeof owner !== 'string' || owner.length === 0) return [];
110
+ const result = runner([
111
+ 'project',
112
+ 'list',
113
+ '--owner',
114
+ owner,
115
+ '--format',
116
+ 'json',
117
+ ]);
118
+ if (result.error || result.status !== 0) return [];
119
+ // `gh project list --format json` emits `{ "projects": [...] }`, not a
120
+ // bare array. Unwrap the envelope before mapping titles.
121
+ const trimmed = (result.stdout || '').trim();
122
+ if (trimmed.length === 0) return [];
123
+ let parsed;
124
+ try {
125
+ parsed = JSON.parse(trimmed);
126
+ } catch {
127
+ return [];
128
+ }
129
+ const projects = Array.isArray(parsed)
130
+ ? parsed
131
+ : Array.isArray(parsed?.projects)
132
+ ? parsed.projects
133
+ : [];
134
+ // Return `{ label, value }` choices: the menu shows the human-readable
135
+ // title, but the resolved value is the numeric Projects V2 number that
136
+ // the `projectNumber` question's validator (and the downstream GitHub
137
+ // provider) require. Mapping the title into the numeric field would store
138
+ // a non-numeric string and break project resolution.
139
+ return projects
140
+ .map((item) => {
141
+ if (!item || typeof item !== 'object') return undefined;
142
+ const number = item.number;
143
+ if (typeof number !== 'number' || !Number.isInteger(number)) {
144
+ return undefined;
145
+ }
146
+ const title =
147
+ typeof item.title === 'string' && item.title.length > 0
148
+ ? item.title
149
+ : String(number);
150
+ return { label: `${title} (#${number})`, value: String(number) };
151
+ })
152
+ .filter((choice) => choice !== undefined);
153
+ }