@webpresso/agent-kit 3.1.28 → 3.2.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.

Potentially problematic release.


This version of @webpresso/agent-kit might be problematic. Click here for more details.

Files changed (329) hide show
  1. package/README.md +53 -15
  2. package/bin/_run.js +179 -19
  3. package/catalog/AGENTS.md.tpl +6 -6
  4. package/catalog/agent/agents/implementer.md +45 -0
  5. package/catalog/agent/rules/ci-cost-local-first.md +139 -0
  6. package/catalog/agent/rules/ci-test-perf.md +5 -1
  7. package/catalog/agent/rules/cmd-execution.md +9 -0
  8. package/catalog/agent/rules/parallel-orchestration-quota.md +100 -0
  9. package/catalog/agent/rules/pre-implementation.md +30 -2
  10. package/catalog/agent/rules/supported-agent-clis.md +9 -0
  11. package/catalog/agent/rules/test-scan-perf.md +80 -0
  12. package/catalog/agent/rules/typescript-version.md +50 -0
  13. package/catalog/agent/rules/workflow-skills-routing.md +4 -2
  14. package/catalog/agent/skills/codex/SKILL.md +25 -1
  15. package/catalog/agent/skills/fix/SKILL.md +3 -0
  16. package/catalog/agent/skills/verify/SKILL.md +22 -2
  17. package/catalog/docs/templates/blueprint.md +1 -1
  18. package/dist/esm/audit/agents.js +1 -0
  19. package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +12 -0
  20. package/dist/esm/audit/blueprint-lifecycle-sql.js +23 -2
  21. package/dist/esm/audit/blueprint-pr-coverage.js +72 -7
  22. package/dist/esm/audit/ci-guardrails-wiring.d.ts +22 -0
  23. package/dist/esm/audit/ci-guardrails-wiring.js +90 -0
  24. package/dist/esm/audit/ci-test-perf.js +30 -0
  25. package/dist/esm/audit/command-surface.js +4 -2
  26. package/dist/esm/audit/host-substitution-risk.d.ts +2 -0
  27. package/dist/esm/audit/host-substitution-risk.js +256 -0
  28. package/dist/esm/audit/registry.d.ts +4 -4
  29. package/dist/esm/audit/registry.js +11 -1
  30. package/dist/esm/audit/roadmap-links.js +6 -0
  31. package/dist/esm/audit/test-scan-perf.d.ts +18 -0
  32. package/dist/esm/audit/test-scan-perf.js +275 -0
  33. package/dist/esm/audit/toolchain-isolation.js +1 -2
  34. package/dist/esm/audit/typescript-version.d.ts +2 -0
  35. package/dist/esm/audit/typescript-version.js +123 -0
  36. package/dist/esm/blueprint/core/parser.js +43 -1
  37. package/dist/esm/blueprint/core/validation/criteria.d.ts +14 -0
  38. package/dist/esm/blueprint/core/validation/criteria.js +41 -2
  39. package/dist/esm/blueprint/core/validation/state.js +25 -14
  40. package/dist/esm/blueprint/db/migrations/run.js +4 -2
  41. package/dist/esm/blueprint/lifecycle/audit.d.ts +20 -0
  42. package/dist/esm/blueprint/lifecycle/audit.js +65 -10
  43. package/dist/esm/blueprint/lifecycle/canonicalize.d.ts +6 -0
  44. package/dist/esm/blueprint/lifecycle/canonicalize.js +135 -0
  45. package/dist/esm/blueprint/lifecycle/engine.d.ts +9 -0
  46. package/dist/esm/blueprint/lifecycle/engine.js +53 -6
  47. package/dist/esm/blueprint/lifecycle/local.d.ts +2 -1
  48. package/dist/esm/blueprint/lifecycle/local.js +19 -3
  49. package/dist/esm/blueprint/lifecycle/review-provenance.d.ts +6 -0
  50. package/dist/esm/blueprint/lifecycle/review-provenance.js +118 -12
  51. package/dist/esm/blueprint/markdown/helpers.js +6 -2
  52. package/dist/esm/blueprint/service/BlueprintCreationService.d.ts +1 -0
  53. package/dist/esm/blueprint/service/BlueprintCreationService.js +53 -4
  54. package/dist/esm/blueprint/service/blueprint-tech-debt-links.js +16 -2
  55. package/dist/esm/blueprint/trust/command-runner.d.ts +26 -0
  56. package/dist/esm/blueprint/trust/command-runner.js +148 -0
  57. package/dist/esm/blueprint/trust/gates.d.ts +7 -0
  58. package/dist/esm/blueprint/trust/gates.js +20 -0
  59. package/dist/esm/blueprint/trust/promotion.d.ts +8 -0
  60. package/dist/esm/blueprint/trust/promotion.js +62 -112
  61. package/dist/esm/blueprint/trust/scaffold.d.ts +19 -0
  62. package/dist/esm/blueprint/trust/scaffold.js +64 -0
  63. package/dist/esm/blueprint/trust/validator.d.ts +1 -0
  64. package/dist/esm/blueprint/trust/validator.js +7 -1
  65. package/dist/esm/blueprint/utils/archive.js +27 -5
  66. package/dist/esm/blueprint/utils/document-paths.d.ts +18 -0
  67. package/dist/esm/blueprint/utils/document-paths.js +45 -12
  68. package/dist/esm/build/cli-mcp-parity.js +10 -0
  69. package/dist/esm/ci/act-replay.js +110 -7
  70. package/dist/esm/ci/act-runner.d.ts +4 -0
  71. package/dist/esm/ci/act-runner.js +85 -26
  72. package/dist/esm/ci/act-worktree-git.d.ts +11 -0
  73. package/dist/esm/ci/act-worktree-git.js +219 -0
  74. package/dist/esm/cli/bundle/commands/blueprint.d.ts +1 -0
  75. package/dist/esm/cli/bundle/commands/blueprint.js +1 -0
  76. package/dist/esm/cli/cli.d.ts +1 -1
  77. package/dist/esm/cli/cli.js +34 -0
  78. package/dist/esm/cli/commands/agent-launch.d.ts +6 -1
  79. package/dist/esm/cli/commands/agent-launch.js +82 -4
  80. package/dist/esm/cli/commands/audit-core.d.ts +1 -1
  81. package/dist/esm/cli/commands/audit-core.js +8 -1
  82. package/dist/esm/cli/commands/audit.js +20 -5
  83. package/dist/esm/cli/commands/blueprint/execution.js +18 -6
  84. package/dist/esm/cli/commands/blueprint/mutations.js +83 -47
  85. package/dist/esm/cli/commands/blueprint/router-dispatch.d.ts +2 -1
  86. package/dist/esm/cli/commands/blueprint/router-dispatch.js +20 -1
  87. package/dist/esm/cli/commands/blueprint/router-output.d.ts +21 -0
  88. package/dist/esm/cli/commands/blueprint/router-output.js +48 -17
  89. package/dist/esm/cli/commands/blueprint/router.d.ts +7 -0
  90. package/dist/esm/cli/commands/blueprint/router.js +40 -3
  91. package/dist/esm/cli/commands/ci-preflight.d.ts +13 -2
  92. package/dist/esm/cli/commands/ci-preflight.js +6 -3
  93. package/dist/esm/cli/commands/ci.d.ts +8 -1
  94. package/dist/esm/cli/commands/ci.js +80 -21
  95. package/dist/esm/cli/commands/compile.js +5 -31
  96. package/dist/esm/cli/commands/dash/delivery-status.d.ts +1 -0
  97. package/dist/esm/cli/commands/dash/delivery-status.js +11 -4
  98. package/dist/esm/cli/commands/dash/keymap.js +1 -0
  99. package/dist/esm/cli/commands/dash/launch-preferences.d.ts +15 -0
  100. package/dist/esm/cli/commands/dash/launch-preferences.js +46 -17
  101. package/dist/esm/cli/commands/dash/plan-once-label.d.ts +7 -0
  102. package/dist/esm/cli/commands/dash/plan-once-label.js +5 -0
  103. package/dist/esm/cli/commands/dash/plan-once-membership.d.ts +67 -0
  104. package/dist/esm/cli/commands/dash/plan-once-membership.js +151 -0
  105. package/dist/esm/cli/commands/dash/plan-once-merge.d.ts +143 -0
  106. package/dist/esm/cli/commands/dash/plan-once-merge.js +238 -0
  107. package/dist/esm/cli/commands/dash/plan-once.d.ts +22 -2
  108. package/dist/esm/cli/commands/dash/plan-once.js +41 -4
  109. package/dist/esm/cli/commands/dash/tui/attention-hud.d.ts +9 -0
  110. package/dist/esm/cli/commands/dash/tui/attention-hud.js +9 -0
  111. package/dist/esm/cli/commands/dash/tui/chat-bridge.d.ts +41 -0
  112. package/dist/esm/cli/commands/dash/tui/chat-bridge.js +73 -0
  113. package/dist/esm/cli/commands/dash/tui/chat-mode.d.ts +47 -0
  114. package/dist/esm/cli/commands/dash/tui/chat-mode.js +98 -0
  115. package/dist/esm/cli/commands/dash/tui/frame.d.ts +3 -0
  116. package/dist/esm/cli/commands/dash/tui/frame.js +3 -1
  117. package/dist/esm/cli/commands/dash/tui/palette.d.ts +1 -1
  118. package/dist/esm/cli/commands/dash/tui/palette.js +14 -0
  119. package/dist/esm/cli/commands/dash/tui/runtime.js +239 -4
  120. package/dist/esm/cli/commands/dash/tui/state.d.ts +41 -0
  121. package/dist/esm/cli/commands/dash/tui/state.js +257 -4
  122. package/dist/esm/cli/commands/doctor.js +5 -0
  123. package/dist/esm/cli/commands/format.js +0 -2
  124. package/dist/esm/cli/commands/hook.d.ts +5 -0
  125. package/dist/esm/cli/commands/hook.js +15 -9
  126. package/dist/esm/cli/commands/init/config.d.ts +0 -1
  127. package/dist/esm/cli/commands/init/config.js +3 -6
  128. package/dist/esm/cli/commands/init/convergence-apply.d.ts +24 -0
  129. package/dist/esm/cli/commands/init/convergence-apply.js +221 -0
  130. package/dist/esm/cli/commands/init/convergence-state.d.ts +13 -0
  131. package/dist/esm/cli/commands/init/convergence-state.js +54 -0
  132. package/dist/esm/cli/commands/init/convergence.d.ts +23 -0
  133. package/dist/esm/cli/commands/init/convergence.js +57 -0
  134. package/dist/esm/cli/commands/init/git-convergence.d.ts +19 -0
  135. package/dist/esm/cli/commands/init/git-convergence.js +168 -0
  136. package/dist/esm/cli/commands/init/gitignore-patcher.js +2 -0
  137. package/dist/esm/cli/commands/init/grok-privacy-smoke.d.ts +52 -0
  138. package/dist/esm/cli/commands/init/grok-privacy-smoke.js +91 -0
  139. package/dist/esm/cli/commands/init/host-native-proof.d.ts +18 -0
  140. package/dist/esm/cli/commands/init/host-native-proof.js +88 -0
  141. package/dist/esm/cli/commands/init/host-visibility.d.ts +2 -2
  142. package/dist/esm/cli/commands/init/host-visibility.js +94 -5
  143. package/dist/esm/cli/commands/init/index.d.ts +1 -0
  144. package/dist/esm/cli/commands/init/index.js +326 -173
  145. package/dist/esm/cli/commands/init/mcp-spec.d.ts +57 -0
  146. package/dist/esm/cli/commands/init/mcp-spec.js +273 -0
  147. package/dist/esm/cli/commands/init/merge.d.ts +1 -0
  148. package/dist/esm/cli/commands/init/merge.js +30 -1
  149. package/dist/esm/cli/commands/init/plugin-cache-prune.d.ts +0 -3
  150. package/dist/esm/cli/commands/init/plugin-cache-prune.js +0 -1
  151. package/dist/esm/cli/commands/init/scaffold-agents-md.d.ts +1 -1
  152. package/dist/esm/cli/commands/init/scaffold-agents-md.js +9 -3
  153. package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +11 -0
  154. package/dist/esm/cli/commands/init/scaffold-base-kit.js +56 -1
  155. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.d.ts +5 -6
  156. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.js +6 -13
  157. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.d.ts +14 -8
  158. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/grok.js +41 -24
  159. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.d.ts +2 -0
  160. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +51 -23
  161. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.d.ts +0 -2
  162. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.js +0 -2
  163. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.d.ts +6 -3
  164. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.js +39 -26
  165. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.d.ts +12 -31
  166. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +297 -173
  167. package/dist/esm/cli/commands/init/scaffolders/file-transaction.d.ts +7 -0
  168. package/dist/esm/cli/commands/init/scaffolders/file-transaction.js +58 -0
  169. package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.d.ts +38 -0
  170. package/dist/esm/cli/commands/init/scaffolders/grok-mcp/index.js +73 -0
  171. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.d.ts +21 -0
  172. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.js +559 -63
  173. package/dist/esm/cli/commands/init/untracked-collision.d.ts +14 -0
  174. package/dist/esm/cli/commands/init/untracked-collision.js +42 -0
  175. package/dist/esm/cli/commands/logs.d.ts +15 -0
  176. package/dist/esm/cli/commands/logs.js +192 -3
  177. package/dist/esm/cli/commands/opencode-rotate.d.ts +49 -0
  178. package/dist/esm/cli/commands/opencode-rotate.js +135 -0
  179. package/dist/esm/cli/commands/public-readiness.d.ts +11 -0
  180. package/dist/esm/cli/commands/public-readiness.js +42 -0
  181. package/dist/esm/cli/commands/quality-log-store.d.ts +1 -0
  182. package/dist/esm/cli/commands/quality-log-store.js +187 -51
  183. package/dist/esm/cli/commands/review.d.ts +35 -3
  184. package/dist/esm/cli/commands/review.js +734 -217
  185. package/dist/esm/cli/commands/run-wait.d.ts +2 -0
  186. package/dist/esm/cli/commands/run-wait.js +122 -0
  187. package/dist/esm/cli/commands/secrets.d.ts +1 -0
  188. package/dist/esm/cli/commands/secrets.js +4 -1
  189. package/dist/esm/cli/commands/setup-help.js +1 -1
  190. package/dist/esm/cli/commands/setup-repair-help.js +1 -1
  191. package/dist/esm/cli/commands/worktree/router-dispatch.js +13 -8
  192. package/dist/esm/cli/direct-provider-launch.js +31 -3
  193. package/dist/esm/cli/optional-tool-freshness.d.ts +27 -0
  194. package/dist/esm/cli/optional-tool-freshness.js +219 -9
  195. package/dist/esm/daemon/domains/git-actions.d.ts +29 -0
  196. package/dist/esm/daemon/domains/git-actions.js +136 -0
  197. package/dist/esm/daemon/domains/run-registry-interop.d.ts +16 -0
  198. package/dist/esm/daemon/domains/run-registry-interop.js +45 -0
  199. package/dist/esm/daemon/domains/sessions-search.d.ts +11 -0
  200. package/dist/esm/daemon/domains/sessions-search.js +29 -0
  201. package/dist/esm/daemon/handlers/blueprints-handlers.d.ts +5 -0
  202. package/dist/esm/daemon/handlers/blueprints-handlers.js +36 -0
  203. package/dist/esm/daemon/handlers/deploy-handlers.d.ts +6 -0
  204. package/dist/esm/daemon/handlers/deploy-handlers.js +5 -0
  205. package/dist/esm/daemon/handlers/fleet-handlers.d.ts +15 -0
  206. package/dist/esm/daemon/handlers/fleet-handlers.js +91 -0
  207. package/dist/esm/daemon/handlers/git-handlers.d.ts +6 -0
  208. package/dist/esm/daemon/handlers/git-handlers.js +27 -0
  209. package/dist/esm/daemon/handlers/product.d.ts +7 -0
  210. package/dist/esm/daemon/handlers/product.js +10 -119
  211. package/dist/esm/daemon/handlers/sessions-handlers.d.ts +12 -0
  212. package/dist/esm/daemon/handlers/sessions-handlers.js +31 -0
  213. package/dist/esm/daemon/handlers/shared.d.ts +5 -0
  214. package/dist/esm/daemon/handlers/shared.js +16 -0
  215. package/dist/esm/daemon/methods.d.ts +8 -1
  216. package/dist/esm/daemon/methods.js +7 -0
  217. package/dist/esm/daemon/protocol/contract.d.ts +43 -0
  218. package/dist/esm/daemon/protocol/contract.js +26 -0
  219. package/dist/esm/daemon/protocol/index.d.ts +1 -1
  220. package/dist/esm/daemon/protocol/index.js +1 -1
  221. package/dist/esm/hooks/__conformance__/matrix.d.ts +6 -0
  222. package/dist/esm/hooks/__conformance__/matrix.js +137 -0
  223. package/dist/esm/hooks/conformance/batch.js +5 -0
  224. package/dist/esm/hooks/doctor.d.ts +15 -0
  225. package/dist/esm/hooks/doctor.js +79 -8
  226. package/dist/esm/hooks/permission-request/index.js +9 -3
  227. package/dist/esm/hooks/permission-request/policy.d.ts +9 -0
  228. package/dist/esm/hooks/permission-request/policy.js +13 -0
  229. package/dist/esm/hooks/pretool-guard/dev-routing.d.ts +9 -0
  230. package/dist/esm/hooks/pretool-guard/dev-routing.js +41 -5
  231. package/dist/esm/hooks/pretool-guard/logger.d.ts +7 -0
  232. package/dist/esm/hooks/pretool-guard/logger.js +16 -0
  233. package/dist/esm/hooks/pretool-guard/runner.d.ts +6 -0
  234. package/dist/esm/hooks/pretool-guard/runner.js +68 -16
  235. package/dist/esm/hooks/pretool-guard/validators/blueprint.js +30 -10
  236. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +58 -4
  237. package/dist/esm/hooks/pretool-guard/validators/index.d.ts +7 -0
  238. package/dist/esm/hooks/pretool-guard/validators/index.js +21 -0
  239. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +0 -1
  240. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +8 -5
  241. package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +19 -0
  242. package/dist/esm/hooks/pretool-guard/validators/path-contract.js +25 -8
  243. package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.d.ts +9 -7
  244. package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.js +126 -14
  245. package/dist/esm/hooks/shared/guard-outcome.d.ts +149 -0
  246. package/dist/esm/hooks/shared/guard-outcome.js +215 -0
  247. package/dist/esm/hooks/shared/hook-bootstrap.d.ts +26 -0
  248. package/dist/esm/hooks/shared/hook-bootstrap.js +64 -1
  249. package/dist/esm/hooks/shared/types.d.ts +8 -5
  250. package/dist/esm/hooks/shared/types.js +23 -8
  251. package/dist/esm/hooks/stop/qa-changed-files.d.ts +11 -0
  252. package/dist/esm/hooks/stop/qa-changed-files.js +74 -0
  253. package/dist/esm/mcp/blueprint/_shared/lifecycle.js +14 -1
  254. package/dist/esm/mcp/blueprint/handlers/document-mutations.js +78 -4
  255. package/dist/esm/mcp/blueprint/handlers/review-log.js +8 -1
  256. package/dist/esm/mcp/blueprint/handlers/task-advance.js +113 -54
  257. package/dist/esm/mcp/blueprint/handlers/task-verify.js +39 -19
  258. package/dist/esm/mcp/blueprint/registration.js +3 -2
  259. package/dist/esm/mcp/server.d.ts +1 -0
  260. package/dist/esm/mcp/server.js +27 -0
  261. package/dist/esm/mcp/tools/_names.d.ts +1 -1
  262. package/dist/esm/mcp/tools/_names.js +5 -0
  263. package/dist/esm/mcp/tools/_registry.js +10 -0
  264. package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
  265. package/dist/esm/mcp/tools/_shared/result.js +44 -1
  266. package/dist/esm/mcp/tools/audit.d.ts +5 -1
  267. package/dist/esm/mcp/tools/audit.js +40 -0
  268. package/dist/esm/mcp/tools/audits.d.ts +4 -0
  269. package/dist/esm/mcp/tools/ci-act.js +9 -11
  270. package/dist/esm/mcp/tools/ci-preflight.d.ts +50 -0
  271. package/dist/esm/mcp/tools/ci-preflight.js +183 -0
  272. package/dist/esm/mcp/tools/pr-upsert.js +39 -1
  273. package/dist/esm/mcp/tools/review-run.d.ts +28 -0
  274. package/dist/esm/mcp/tools/review-run.js +216 -0
  275. package/dist/esm/mcp/tools/run-wait.d.ts +86 -0
  276. package/dist/esm/mcp/tools/run-wait.js +593 -0
  277. package/dist/esm/mcp/tools/session-id.d.ts +3 -0
  278. package/dist/esm/mcp/tools/session-id.js +45 -0
  279. package/dist/esm/mcp/tools/session-info.d.ts +3 -0
  280. package/dist/esm/mcp/tools/session-info.js +49 -0
  281. package/dist/esm/output-transforms/audit.d.ts +23 -0
  282. package/dist/esm/output-transforms/audit.js +47 -0
  283. package/dist/esm/output-transforms/index.js +2 -0
  284. package/dist/esm/paths/state-root.js +3 -0
  285. package/dist/esm/review/authority.js +30 -7
  286. package/dist/esm/review/availability.d.ts +22 -0
  287. package/dist/esm/review/availability.js +123 -23
  288. package/dist/esm/review/delivery-verifier.d.ts +27 -0
  289. package/dist/esm/review/delivery-verifier.js +115 -0
  290. package/dist/esm/review/events.d.ts +3 -2
  291. package/dist/esm/review/events.js +23 -3
  292. package/dist/esm/review/execution/adapters.js +26 -9
  293. package/dist/esm/review/execution/output-policy.d.ts +2 -0
  294. package/dist/esm/review/execution/output-policy.js +12 -0
  295. package/dist/esm/review/execution/review-checkout.js +87 -6
  296. package/dist/esm/review/execution/supervisor.js +5 -0
  297. package/dist/esm/review/execution/types.d.ts +8 -0
  298. package/dist/esm/review/opencode-account.d.ts +24 -0
  299. package/dist/esm/review/opencode-account.js +68 -0
  300. package/dist/esm/review/opencode-auth.d.ts +33 -0
  301. package/dist/esm/review/opencode-auth.js +79 -0
  302. package/dist/esm/review/subject.d.ts +27 -0
  303. package/dist/esm/review/subject.js +179 -32
  304. package/dist/esm/runtime/executor.d.ts +1 -0
  305. package/dist/esm/runtime/executor.js +2 -1
  306. package/dist/esm/runtime/opencode-account-materializer.d.ts +34 -0
  307. package/dist/esm/runtime/opencode-account-materializer.js +33 -0
  308. package/dist/esm/secret-gate/runner.d.ts +1 -0
  309. package/dist/esm/secret-gate/runner.js +4 -1
  310. package/dist/esm/status/snapshot.js +30 -19
  311. package/dist/esm/test/duration-sequencer.d.ts +20 -0
  312. package/dist/esm/test/duration-sequencer.js +54 -0
  313. package/dist/esm/test/shard-durations.json +922 -0
  314. package/dist/esm/test/worker-budget.d.ts +6 -0
  315. package/dist/esm/test/worker-budget.js +59 -1
  316. package/dist/esm/test-helpers/global-setup.d.ts +1 -1
  317. package/dist/esm/test-helpers/global-setup.js +68 -24
  318. package/dist/esm/ultragoal/service.d.ts +7 -0
  319. package/dist/esm/ultragoal/service.js +42 -2
  320. package/dist/esm/utils/write-json-file.js +3 -1
  321. package/dist/esm/worktrees/codex-project-trust.d.ts +15 -0
  322. package/dist/esm/worktrees/codex-project-trust.js +56 -0
  323. package/dist/esm/worktrees/current.d.ts +1 -0
  324. package/dist/esm/worktrees/current.js +1 -0
  325. package/dist/esm/worktrees/project-agent-surfaces.d.ts +1 -0
  326. package/dist/esm/worktrees/project-agent-surfaces.js +2 -1
  327. package/dist/esm/worktrees/registry.d.ts +8 -0
  328. package/dist/esm/worktrees/registry.js +18 -3
  329. package/package.json +18 -15
@@ -24,9 +24,9 @@ import { getBlueprintDocumentPaths } from "#utils/document-paths.js";
24
24
  import { resolveBlueprintRoot } from "#utils/blueprint-root.js";
25
25
  import { reIngestProjection } from "#projection-ready.js";
26
26
  import { assertAllTasksHaveCanonicalPassingEvidence } from "#verification.js";
27
- import { applyPromotionTrustGate } from "#trust/promotion.js";
27
+ import { assertPromotionTrustProofCurrent, preparePromotionTrustGate, } from "#trust/promotion.js";
28
28
  import matter from "gray-matter";
29
- import { evaluateApprovalGate, formatApprovalGateRequirement } from "#lifecycle/audit";
29
+ import { assertCompletedApprovalGate, evaluateApprovalGate, formatApprovalGateRequirement, } from "#lifecycle/audit";
30
30
  /**
31
31
  * Module-level factory. `null` = use the production default (loadSyncCredentials
32
32
  * from auth.ts + BlueprintSyncClient + ReplicaManager — lazy-imported so that
@@ -161,6 +161,31 @@ async function reIngestDb(cwd) {
161
161
  return;
162
162
  await reIngestProjection(cwd);
163
163
  }
164
+ /**
165
+ * Force reingest of one blueprint document even when the stored content hash
166
+ * still matches. Used on complete so task-table lag cannot block finalize.
167
+ */
168
+ async function forceReIngestBlueprint(cwd, slug, documentPath) {
169
+ const target = dbPath(cwd);
170
+ if (!existsSync(target))
171
+ return;
172
+ try {
173
+ const conn = openDb(target);
174
+ try {
175
+ // Invalidate hash so ingestAll's skip-if-unchanged path rewrites tasks.
176
+ conn.db.prepare(`UPDATE blueprints SET content_hash = NULL WHERE slug = ?`).run(slug);
177
+ }
178
+ finally {
179
+ conn.close();
180
+ }
181
+ await reIngestProjection(cwd);
182
+ }
183
+ catch {
184
+ // Projection is best-effort for complete; markdown gate already passed.
185
+ // Swallow so a broken local projection cannot block lifecycle completion.
186
+ void documentPath;
187
+ }
188
+ }
164
189
  /**
165
190
  * Update `status:` in YAML frontmatter. Preserves everything else verbatim.
166
191
  */
@@ -296,19 +321,38 @@ async function advanceTaskLocked(cwd, blueprintSlug, taskId, toStatus) {
296
321
  * - Re-ingests into DB
297
322
  */
298
323
  export async function promoteBlueprint(cwd, slug, toState) {
324
+ const adapter = await resolveSyncAdapterForCli(cwd);
325
+ // Pull platform state under the mutation lock, then release it before any
326
+ // Trust Dossier command spawns a child `wp`. Child startup/ingestion can
327
+ // legitimately need the same repo-scoped lock.
328
+ await withMarkdownWriteLock(cwd, () => runCliPlatformMutationSync(adapter, {
329
+ label: "wp_blueprint_promote",
330
+ ensureFreshSlug: slug,
331
+ }));
332
+ const found = findBlueprintDocument(resolveBlueprintRoot(cwd), slug);
333
+ if (!found) {
334
+ throw new Error(`Blueprint "${slug}" not found in any state directory under ${resolveBlueprintRoot(cwd)}`);
335
+ }
336
+ const crossesDraftApprovalBoundary = found.state === "draft" && (toState === "planned" || toState === "in-progress");
337
+ const trustProof = crossesDraftApprovalBoundary
338
+ ? preparePromotionTrustGate({
339
+ repoRoot: cwd,
340
+ file: found.documentPath,
341
+ markdown: readFileSync(found.documentPath, "utf8"),
342
+ })
343
+ : null;
299
344
  // F9/R7: cross-worktree markdown writes serialize via the repo-scoped lock.
300
- return withMarkdownWriteLock(cwd, () => promoteBlueprintLocked(cwd, slug, toState));
345
+ // The proof is revalidated inside this lock before any lifecycle write.
346
+ return withMarkdownWriteLock(cwd, () => promoteBlueprintLocked(cwd, slug, toState, adapter, trustProof));
301
347
  }
302
- async function promoteBlueprintLocked(cwd, slug, toState) {
348
+ async function promoteBlueprintLocked(cwd, slug, toState, adapter, trustProof) {
303
349
  const blueprintRoot = resolveBlueprintRoot(cwd);
304
350
  const found = findBlueprintDocument(blueprintRoot, slug);
305
351
  if (!found) {
306
352
  throw new Error(`Blueprint "${slug}" not found in any state directory under ${blueprintRoot}`);
307
353
  }
308
354
  const { dir: currentDir, documentPath: currentDocumentPath, shape, state: currentState } = found;
309
- // Guard: refuse to complete if any tasks are not done/dropped
310
- if (toState === "completed") {
311
- const markdown = readFileSync(currentDocumentPath, "utf8");
355
+ const assertCompletionReady = (markdown) => {
312
356
  const blueprint = parseBlueprint(markdown, slug);
313
357
  if (blueprint.tasks.length === 0) {
314
358
  throw new Error(`Cannot promote "${slug}" to completed: zero-task blueprints cannot complete through the public lifecycle surface`);
@@ -319,43 +363,30 @@ async function promoteBlueprintLocked(cwd, slug, toState) {
319
363
  throw new Error(`Cannot promote "${slug}" to completed: the following tasks are not done/dropped: ${list}`);
320
364
  }
321
365
  assertAllTasksHaveCanonicalPassingEvidence(markdown, blueprint.tasks.filter((task) => task.status === "done").map((task) => task.id));
322
- const target = dbPath(cwd);
323
- if (existsSync(target)) {
324
- const conn = openDb(target);
325
- let openTasks;
326
- try {
327
- openTasks = conn.db
328
- .prepare(`SELECT task_id, status FROM tasks WHERE blueprint_slug = ? AND status NOT IN ('done', 'dropped')`)
329
- .all(slug);
330
- }
331
- finally {
332
- conn.close();
333
- }
334
- if (openTasks.length > 0) {
335
- const list = openTasks.map((t) => `${t.task_id} (${t.status})`).join(", ");
336
- throw new Error(`Cannot promote "${slug}" to completed: the following tasks are not done: ${list}`);
337
- }
366
+ // Completion parity with CI: the CLI completion owner uses the same
367
+ // audit-owned gate as the MCP funnel and execution engine, so all normal
368
+ // paths into `completed` enforce the same plan-purpose approval.
369
+ try {
370
+ assertCompletedApprovalGate(currentDocumentPath, markdown);
338
371
  }
339
- }
340
- // Platform freshness must be resolved before trust validation so the proof
341
- // applies to the current replica, not stale local markdown.
342
- // Iron rule: resolveSyncAdapterForCli() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
343
- const adapter = await resolveSyncAdapterForCli(cwd);
344
- await runCliPlatformMutationSync(adapter, {
345
- label: "wp_blueprint_promote",
346
- ensureFreshSlug: slug,
347
- });
372
+ catch (error) {
373
+ throw new Error(`Cannot complete "${slug}": ${error instanceof Error ? error.message : String(error)}`);
374
+ }
375
+ };
348
376
  // Trust must be proven before any platform status_changed event is published.
349
377
  let content = readFileSync(currentDocumentPath, "utf8");
350
378
  let trustedSource = content;
379
+ if (toState === "completed") {
380
+ assertCompletionReady(content);
381
+ }
351
382
  const crossesDraftApprovalBoundary = currentState === "draft" && (toState === "planned" || toState === "in-progress");
352
383
  if (crossesDraftApprovalBoundary) {
353
- content = applyPromotionTrustGate({
354
- repoRoot: cwd,
355
- file: currentDocumentPath,
356
- markdown: content,
357
- });
358
- trustedSource = readFileSync(currentDocumentPath, "utf8");
384
+ if (trustProof === null) {
385
+ throw new Error("Blueprint trust gate invalidated: no external gate proof is available");
386
+ }
387
+ assertPromotionTrustProofCurrent({ repoRoot: cwd, file: currentDocumentPath, markdown: content }, trustProof);
388
+ content = trustProof.trustedMarkdown;
389
+ trustedSource = trustProof.sourceMarkdown;
359
390
  // Governance Piece 1 — HARD gate at the promotion boundary. One
360
391
  // provenance-backed Claude/Codex/Grok or OpenCode-Go model approval can
361
392
  // promote. Check AFTER the trust gate so trust failures surface first.
@@ -385,18 +416,23 @@ async function promoteBlueprintLocked(cwd, slug, toState) {
385
416
  if (crossesDraftApprovalBoundary) {
386
417
  const refreshedSource = readFileSync(currentDocumentPath, "utf8");
387
418
  if (refreshedSource !== trustedSource) {
388
- content = applyPromotionTrustGate({
389
- repoRoot: cwd,
390
- file: currentDocumentPath,
391
- markdown: refreshedSource,
392
- });
393
- const approvalEvaluation = evaluateApprovalGate(currentDocumentPath, matter(content).data.approvals);
394
- if (!approvalEvaluation.satisfied) {
395
- throw new Error(`Cannot promote "${slug}" to ${toState}: frontmatter \`approvals:\` does not satisfy the promotion reviewer mix (${formatApprovalGateRequirement(approvalEvaluation)}). Record approvals, commit the matching review ledger (e.g. reviews.md), and include tracked review transcript/artifact files referenced by each structured review entry — see catalog/agent/rules/pre-implementation.md.`);
396
- }
419
+ throw new Error(`Cannot promote "${slug}" to ${toState}: blueprint changed after external trust gates ran; retry promotion`);
397
420
  }
421
+ assertPromotionTrustProofCurrent({ repoRoot: cwd, file: currentDocumentPath, markdown: refreshedSource }, trustProof);
422
+ }
423
+ if (toState === "completed") {
424
+ // The platform pull can replace the document after the first completion
425
+ // check. Re-read and re-assert against the exact content written below.
426
+ content = readFileSync(currentDocumentPath, "utf8");
427
+ assertCompletionReady(content);
398
428
  }
399
429
  }
430
+ if (toState === "completed") {
431
+ // Best-effort projection refresh. Clear content hash first so a lagging
432
+ // tasks table is rewritten even when a prior corrupt UPDATE left the
433
+ // stored hash equal to current markdown.
434
+ await forceReIngestBlueprint(cwd, slug, currentDocumentPath);
435
+ }
400
436
  // Always update local markdown + SQLite.
401
437
  // Platform-first: these become derived artifacts; disabled: these are canonical.
402
438
  // Update frontmatter in the current location first, then move
@@ -1,6 +1,6 @@
1
1
  import type { BlueprintAuditResult, BlueprintSummary } from "#local";
2
2
  import type { BlueprintTemplateEntry } from "#sync/types.js";
3
- import type { AdvanceTaskResult, BlueprintCommandOptions, BlueprintLifecycleMutationResult, CreateBlueprintResult, ExportBlueprintResult, ExecuteBlueprintResult, MoveBlueprintResult, PromoteBlueprintResult, ShowBlueprintResult } from "./router.js";
3
+ import type { AdvanceTaskResult, BlueprintCommandOptions, BlueprintCanonicalizeResult, BlueprintLifecycleMutationResult, CreateBlueprintResult, ExportBlueprintResult, ExecuteBlueprintResult, MoveBlueprintResult, PromoteBlueprintResult, ShowBlueprintResult } from "./router.js";
4
4
  /**
5
5
  * Override the platform template fetcher — for tests only.
6
6
  * Pass `null` to restore the production default.
@@ -21,6 +21,7 @@ export declare class BlueprintAuditFailedError extends Error {
21
21
  interface BlueprintCommandDependencies {
22
22
  advanceBlueprintTask: (slug: string, taskId: string, toStatus: string, options: BlueprintCommandOptions) => Promise<AdvanceTaskResult>;
23
23
  auditBlueprints: (options: BlueprintCommandOptions) => Promise<BlueprintAuditResult>;
24
+ canonicalizeBlueprintBySlug: (slug: string, options: BlueprintCommandOptions) => Promise<BlueprintCanonicalizeResult>;
24
25
  controlBlueprintExec: (action: "status" | "resume" | "stop", slug: string, options: BlueprintCommandOptions) => Promise<ExecuteBlueprintResult>;
25
26
  readBlueprintExecutionLogs: (slug: string, options: BlueprintCommandOptions) => Promise<ExecuteBlueprintResult>;
26
27
  createBlueprint: (goal: string, options: BlueprintCommandOptions) => Promise<CreateBlueprintResult>;
@@ -3,7 +3,9 @@ import { tmpdir } from "node:os";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import path from "node:path";
5
5
  import { executeBlueprintDbSubcommand } from "./db-commands.js";
6
+ import { getBlueprintSubcommandNames } from "./router-output.js";
6
7
  import { listTemplates, resolveTemplate } from "./template-resolver.js";
8
+ import { TRUST_DOSSIER_SCAFFOLD } from "#trust/scaffold.js";
7
9
  // ---------------------------------------------------------------------------
8
10
  // Platform template fetcher (injectable for tests)
9
11
  // ---------------------------------------------------------------------------
@@ -232,6 +234,15 @@ export async function executeBlueprintSubcommand(subcommand, args, options, deps
232
234
  deps.printBlueprintOutput(options.json ? result : result.message, options.json);
233
235
  return;
234
236
  }
237
+ case "canonicalize": {
238
+ const slug = args[0];
239
+ if (!slug) {
240
+ throw new Error("Usage: wp blueprint canonicalize <slug>");
241
+ }
242
+ const result = await deps.canonicalizeBlueprintBySlug(slug, options);
243
+ deps.printBlueprintOutput(options.json ? { from: result.from, to: result.to, moved: result.moved } : result.message, options.json);
244
+ return;
245
+ }
235
246
  case "start": {
236
247
  const slug = args[0];
237
248
  if (!slug) {
@@ -350,8 +361,16 @@ export async function executeBlueprintSubcommand(subcommand, args, options, deps
350
361
  deps.printBlueprintOutput(options.json ? result : result.message, options.json);
351
362
  return;
352
363
  }
364
+ case "trust-dossier": {
365
+ // Read-only: prints an already-valid "## Trust Dossier" starter block
366
+ // (src/blueprint/trust/scaffold.ts). No file writes, no worktree/lock
367
+ // interaction — an author pastes the output into their overview and
368
+ // edits the example values.
369
+ deps.printBlueprintOutput(options.json ? { markdown: TRUST_DOSSIER_SCAFFOLD } : TRUST_DOSSIER_SCAFFOLD, options.json);
370
+ return;
371
+ }
353
372
  default: {
354
- throw new Error(`Unknown blueprint subcommand: ${subcommand}\n\nUse one of: list, new, show, exec, start, park, task, finalize, promote, audit, move, control, logs, db, export`);
373
+ throw new Error(`Unknown blueprint subcommand: ${subcommand}\n\nUse one of: ${getBlueprintSubcommandNames().join(", ")}`);
355
374
  }
356
375
  }
357
376
  }
@@ -1,7 +1,28 @@
1
1
  import type { Blueprint, BlueprintAuditResult, BlueprintSummary } from "#local";
2
2
  import type { CreateBlueprintResult, ExecuteBlueprintResult, ShowBlueprintResult } from "./router.js";
3
+ /**
4
+ * Canonical registry of every subcommand `router-dispatch.ts` actually
5
+ * dispatches. This is the single source of truth for both the `--help`
6
+ * `Commands:` block (see `BLUEPRINT_HELP` below) and the unknown-subcommand
7
+ * error list — so a subcommand can't ship dispatched-but-undocumented
8
+ * again. `router-dispatch.test.ts` asserts this list stays equal to the
9
+ * live `case "…":` labels in the dispatch switch.
10
+ */
11
+ export interface BlueprintSubcommandSpec {
12
+ /** Matches a `case "<name>":` label in router-dispatch.ts exactly. */
13
+ readonly name: string;
14
+ /** One or more `Commands:` lines (without the leading indent). */
15
+ readonly usage: readonly string[];
16
+ }
17
+ export declare const BLUEPRINT_SUBCOMMANDS: readonly BlueprintSubcommandSpec[];
3
18
  export declare function formatTaskLine(task: Blueprint["tasks"][number]): string;
4
19
  export declare function getBlueprintHelpText(): string;
20
+ /**
21
+ * Subcommand names in registry order, for the unknown-subcommand error
22
+ * message. Kept as a function (rather than exporting a derived constant)
23
+ * so the source of truth stays singular: `BLUEPRINT_SUBCOMMANDS`.
24
+ */
25
+ export declare function getBlueprintSubcommandNames(): readonly string[];
5
26
  export interface BlueprintInventorySummary {
6
27
  total: number;
7
28
  byStatus: Record<string, number>;
@@ -1,25 +1,48 @@
1
1
  import { buildRoadmapModel, planStatusSchema } from "#local";
2
+ export const BLUEPRINT_SUBCOMMANDS = [
3
+ { name: "list", usage: ["list [status]"] },
4
+ {
5
+ name: "new",
6
+ usage: ["new <goal> --complexity <XS|S|M|L|XL> [--type <blueprint|parent-roadmap>]"],
7
+ },
8
+ { name: "show", usage: ["show <slug>"] },
9
+ {
10
+ name: "exec",
11
+ usage: [
12
+ "exec <slug>",
13
+ "exec status <slug>",
14
+ "exec resume <slug>",
15
+ "exec stop <slug>",
16
+ "exec logs <slug>",
17
+ ],
18
+ },
19
+ { name: "start", usage: ["start <slug>"] },
20
+ { name: "park", usage: ["park <slug>"] },
21
+ {
22
+ name: "task",
23
+ usage: [
24
+ "task start <slug> <taskId>",
25
+ "task block <slug> <taskId> --reason <text>",
26
+ "task unblock <slug> <taskId>",
27
+ "task complete <slug> <taskId>",
28
+ ],
29
+ },
30
+ { name: "finalize", usage: ["finalize <slug>"] },
31
+ { name: "promote", usage: ["promote <slug> <planned|in-progress|completed|parked>"] },
32
+ { name: "audit", usage: ["audit [--staged|--all] [--strict]"] },
33
+ { name: "move", usage: ["move <slug> <status> --force-recovery"] },
34
+ { name: "canonicalize", usage: ["canonicalize <slug>"] },
35
+ { name: "control", usage: ["control <status|resume|stop> <slug>"] },
36
+ { name: "logs", usage: ["logs <slug>"] },
37
+ { name: "db", usage: ["db <verb> [...args]"] },
38
+ { name: "export", usage: ["export --format spec-kit <slug>"] },
39
+ { name: "trust-dossier", usage: ["trust-dossier"] },
40
+ ];
2
41
  const BLUEPRINT_HELP = [
3
42
  "Blueprint management",
4
43
  "",
5
44
  "Commands:",
6
- " list [status]",
7
- " new <goal> --complexity <XS|S|M|L|XL> [--type <blueprint|parent-roadmap>]",
8
- " show <slug>",
9
- " exec <slug>",
10
- " exec status <slug>",
11
- " exec resume <slug>",
12
- " exec stop <slug>",
13
- " exec logs <slug>",
14
- " start <slug>",
15
- " park <slug>",
16
- " task start <slug> <taskId>",
17
- " task block <slug> <taskId> --reason <text>",
18
- " task unblock <slug> <taskId>",
19
- " task complete <slug> <taskId>",
20
- " finalize <slug>",
21
- " audit [--staged|--all] [--strict]",
22
- " move <slug> <status> --force-recovery",
45
+ ...BLUEPRINT_SUBCOMMANDS.flatMap((spec) => spec.usage.map((line) => ` ${line}`)),
23
46
  ].join("\n");
24
47
  export function formatTaskLine(task) {
25
48
  const checkbox = task.status === "done" || task.status === "dropped" ? "x" : " ";
@@ -28,6 +51,14 @@ export function formatTaskLine(task) {
28
51
  export function getBlueprintHelpText() {
29
52
  return BLUEPRINT_HELP;
30
53
  }
54
+ /**
55
+ * Subcommand names in registry order, for the unknown-subcommand error
56
+ * message. Kept as a function (rather than exporting a derived constant)
57
+ * so the source of truth stays singular: `BLUEPRINT_SUBCOMMANDS`.
58
+ */
59
+ export function getBlueprintSubcommandNames() {
60
+ return BLUEPRINT_SUBCOMMANDS.map((spec) => spec.name);
61
+ }
31
62
  export function summarizeBlueprintInventory(summaries) {
32
63
  const byStatus = Object.fromEntries(planStatusSchema.options.toSorted().map((status) => [status, 0]));
33
64
  const byType = {
@@ -73,6 +73,12 @@ export interface BlueprintLifecycleMutationResult {
73
73
  status: string;
74
74
  taskId?: string;
75
75
  }
76
+ export interface BlueprintCanonicalizeResult {
77
+ from: string;
78
+ to: string;
79
+ moved: boolean;
80
+ message: string;
81
+ }
76
82
  export interface CreateBlueprintResult extends CreatedBlueprint {
77
83
  message: string;
78
84
  /** True when draft was auto-routed off a primary-like checkout (H-009 DX). */
@@ -123,6 +129,7 @@ export declare function exportBlueprint(slug: string, format: string, options?:
123
129
  export declare function advanceBlueprintTask(slug: string, taskId: string, toStatus: string, options?: BlueprintMoveOptions): Promise<AdvanceTaskResult>;
124
130
  export declare function promoteBlueprintToState(slug: string, toState: string, options?: BlueprintMoveOptions): Promise<PromoteBlueprintResult>;
125
131
  export declare function finalizeBlueprintBySlug(slug: string, options?: BlueprintMoveOptions): Promise<PromoteBlueprintResult>;
132
+ export declare function canonicalizeBlueprintBySlug(slug: string, options?: BlueprintMoveOptions): Promise<BlueprintCanonicalizeResult>;
126
133
  export declare function registerBlueprintRouter(cli: CAC): void;
127
134
  export declare function _setBlueprintExecCommandExistsForTests(probe: ((command: string) => boolean) | null): void;
128
135
  export declare function _setBlueprintExecStarterForTests(starter: ((slug: string, options: BlueprintMoveOptions) => Promise<BlueprintLifecycleMutationResult>) | null): void;
@@ -5,9 +5,12 @@ import { parseBlueprintForDb } from "#db/parser/blueprint-db-parser";
5
5
  import { blueprintToSpecKit } from "#export/spec-kit/index";
6
6
  import { getProjectRoot } from "#cli/utils";
7
7
  import { commandExists as defaultCommandExists } from "#runtime/command-exists.js";
8
- import { clearBlueprintWorktreeOwnership, ensureBlueprintOwnerWorktree, } from "#worktrees/manager.js";
8
+ import { adoptBlueprintOwnerWorktree, clearBlueprintWorktreeOwnership, ensureBlueprintOwnerWorktree, } from "#worktrees/manager.js";
9
+ import { resolveCurrentManagedWorktreeContext } from "#worktrees/current.js";
10
+ import { canonicalizeWorktreePath, WORKTREE_PROBE_TIMEOUT_MS } from "#worktrees/identity.js";
9
11
  import { resolveBlueprintRoot } from "#utils/blueprint-root";
10
12
  import { getBlueprintDocumentPaths } from "#utils/document-paths.js";
13
+ import { canonicalizeBlueprint } from "#lifecycle/canonicalize.js";
11
14
  import { applyBlueprintLifecycleToFile, BlueprintCreationService, BlueprintService, complexitySchema, relativeBlueprintSlug, parseBlueprint, planStatusSchema, runBlueprintAudit, resolveBlueprintFile, serializeBlueprint, validateAllTasksDone, } from "#local";
12
15
  import { resolvePackageAssetPreferred } from "#utils/package-assets";
13
16
  import { resolveDraftAuthoringRoot } from "#worktrees/draft-authoring-root.js";
@@ -392,7 +395,16 @@ export async function startBlueprint(slug, options = {}) {
392
395
  if (source.blueprint.status !== "planned") {
393
396
  throw new Error(`Blueprint ${source.slug} must be planned before start (current: ${source.blueprint.status}).`);
394
397
  }
395
- const binding = ensureBlueprintOwnerWorktree(projectRoot, relativeBlueprintSlug(slug));
398
+ const relativeSlug = relativeBlueprintSlug(slug);
399
+ const currentManaged = resolveCurrentManagedWorktreeContext(projectRoot);
400
+ const canonicalProjectRoot = canonicalizeWorktreePath(projectRoot);
401
+ const currentBranch = readCurrentGitBranch(projectRoot);
402
+ const binding = currentManaged &&
403
+ currentManaged.kind === "owner" &&
404
+ currentManaged.worktreePath === canonicalProjectRoot &&
405
+ currentBranch === `bp/${relativeSlug}`
406
+ ? adoptBlueprintOwnerWorktree(currentManaged.repoRoot, relativeSlug, currentManaged.worktreePath)
407
+ : ensureBlueprintOwnerWorktree(projectRoot, relativeSlug);
396
408
  const result = await applyLifecycleMutation(slug, {
397
409
  type: "start",
398
410
  worktreeOwnerId: binding.id,
@@ -404,6 +416,20 @@ export async function startBlueprint(slug, options = {}) {
404
416
  ownerWorktreePath: binding.path,
405
417
  };
406
418
  }
419
+ function readCurrentGitBranch(cwd) {
420
+ try {
421
+ const branch = execFileSync("git", ["branch", "--show-current"], {
422
+ cwd,
423
+ encoding: "utf8",
424
+ timeout: WORKTREE_PROBE_TIMEOUT_MS,
425
+ stdio: ["ignore", "pipe", "ignore"],
426
+ }).trim();
427
+ return branch.length > 0 ? branch : null;
428
+ }
429
+ catch {
430
+ return null;
431
+ }
432
+ }
407
433
  export async function parkBlueprint(slug, options = {}) {
408
434
  const projectRoot = resolveProjectRoot(options.projectRoot);
409
435
  const result = await applyLifecycleMutation(slug, { type: "park" }, projectRoot);
@@ -487,9 +513,19 @@ export async function finalizeBlueprintBySlug(slug, options = {}) {
487
513
  const projectRoot = resolveProjectRoot(options.projectRoot);
488
514
  return finalizeBlueprintMutation(projectRoot, slug);
489
515
  }
516
+ export async function canonicalizeBlueprintBySlug(slug, options = {}) {
517
+ const projectRoot = resolveProjectRoot(options.projectRoot);
518
+ const result = await canonicalizeBlueprint(projectRoot, slug);
519
+ return {
520
+ ...result,
521
+ message: result.moved
522
+ ? `Canonicalized blueprint ${slug}: ${result.from} -> ${result.to}`
523
+ : `Blueprint ${slug} is already canonical: ${result.to}`,
524
+ };
525
+ }
490
526
  export function registerBlueprintRouter(cli) {
491
527
  cli
492
- .command("blueprint [subcommand] [...args]", "Manage blueprints. Use: wp blueprint <action> --help for action-specific options (new, list, show, audit, exec, move, finalize, start, task)")
528
+ .command("blueprint [subcommand] [...args]", "Manage blueprints. Use: wp blueprint <action> --help for action-specific options (new, list, show, audit, exec, move, finalize, start, task, trust-dossier)")
493
529
  .option("--json", "Print JSON output")
494
530
  .option("--no-tui", "Use plain terminal output")
495
531
  .option("--complexity <complexity>", "Blueprint complexity (XS|S|M|L|XL)")
@@ -510,6 +546,7 @@ export function registerBlueprintRouter(cli) {
510
546
  await executeBlueprintSubcommand(subcommand, args, options, {
511
547
  advanceBlueprintTask,
512
548
  auditBlueprints,
549
+ canonicalizeBlueprintBySlug,
513
550
  createBlueprint,
514
551
  controlBlueprintExec,
515
552
  executeBlueprint,
@@ -31,9 +31,20 @@ export interface CiPreflightDeps {
31
31
  readonly cwd?: string;
32
32
  readonly resolveRepoRoot?: (cwd: string) => string | null;
33
33
  readonly hasNodeModules?: (repoRoot: string) => boolean;
34
- readonly runCheck?: (check: CiPreflightCheck, repoRoot: string) => number;
34
+ readonly runCheck?: (check: CiPreflightCheck, repoRoot: string) => number | Promise<number>;
35
35
  readonly stdout?: Pick<typeof process.stdout, "write">;
36
36
  readonly stderr?: Pick<typeof process.stderr, "write">;
37
37
  }
38
- export declare function runCiPreflight(deps?: CiPreflightDeps): number;
38
+ /**
39
+ * Re-invoke the same `wp` runtime that is currently executing so each check
40
+ * runs the real verb (faithful CI parity) rather than a reimplemented copy of
41
+ * its affected-resolution logic. Prefers the repo-local `bin/wp` launcher when
42
+ * present so the exact source/compiled selection and NODE_PATH wiring apply;
43
+ * falls back to the running runtime for consumer repos with a global `wp`.
44
+ */
45
+ export declare function resolveWpLauncher(repoRoot: string): {
46
+ readonly command: string;
47
+ readonly prefixArgs: readonly string[];
48
+ };
49
+ export declare function runCiPreflight(deps?: CiPreflightDeps): Promise<number>;
39
50
  export declare function registerCiPreflightCommand(cli: CAC): void;
@@ -57,7 +57,10 @@ function reproduceLine(check) {
57
57
  * present so the exact source/compiled selection and NODE_PATH wiring apply;
58
58
  * falls back to the running runtime for consumer repos with a global `wp`.
59
59
  */
60
- function resolveWpLauncher(repoRoot) {
60
+ // Exported so `src/mcp/tools/ci-preflight.ts` can re-invoke the exact same
61
+ // `wp` launcher when it substitutes an output-capturing `runCheck` for the
62
+ // default `stdio: "inherit"` spawn — do not duplicate this resolution logic.
63
+ export function resolveWpLauncher(repoRoot) {
61
64
  const localLauncher = path.join(repoRoot, "bin", process.platform === "win32" ? "wp.cmd" : "wp");
62
65
  if (existsSync(localLauncher))
63
66
  return { command: localLauncher, prefixArgs: [] };
@@ -82,7 +85,7 @@ function defaultRunCheck(check, repoRoot) {
82
85
  }
83
86
  return typeof result.status === "number" ? result.status : 1;
84
87
  }
85
- export function runCiPreflight(deps = {}) {
88
+ export async function runCiPreflight(deps = {}) {
86
89
  const cwd = deps.cwd ?? process.cwd();
87
90
  const stdout = deps.stdout ?? process.stdout;
88
91
  const stderr = deps.stderr ?? process.stderr;
@@ -100,7 +103,7 @@ export function runCiPreflight(deps = {}) {
100
103
  }
101
104
  for (const check of CI_PREFLIGHT_CHECKS) {
102
105
  stdout.write(`\nwp ci-preflight: running ${check.label} (${reproduceLine(check)})\n`);
103
- const exitCode = runCheck(check, repoRoot);
106
+ const exitCode = await runCheck(check, repoRoot);
104
107
  if (exitCode !== 0) {
105
108
  const normalizedExit = exitCode === 0 ? 1 : exitCode;
106
109
  stderr.write(`\nwp ci-preflight: ${check.label} failed (exit ${normalizedExit}).\n` +
@@ -2,12 +2,14 @@ import type { CAC } from "cac";
2
2
  import type { SecretGateCommandOptions, SecretGateRunResult } from "#secret-gate/runner.js";
3
3
  import { type CiActEventName, type CiActExecutionMode } from "#ci/act-runner.js";
4
4
  export declare const DEFAULT_CI_ACT_TIMEOUT_MS: number;
5
+ export declare const SMOKE_CI_ACT_TIMEOUT_MS = 30000;
5
6
  export declare const MAX_CI_ACT_TIMEOUT_MS: number;
6
7
  export declare const CI_COMMAND_HELP: string;
7
8
  export interface CiActOptions {
8
9
  readonly workflow?: string;
9
10
  readonly workflowPath?: string;
10
11
  readonly job?: string;
12
+ readonly matrix?: readonly string[];
11
13
  readonly eventName?: CiActEventName;
12
14
  readonly eventPath?: string;
13
15
  readonly envProfile?: string;
@@ -17,6 +19,7 @@ export interface CiActOptions {
17
19
  readonly platformImage?: string;
18
20
  readonly execute?: boolean;
19
21
  readonly timeoutMs?: number;
22
+ readonly smoke?: boolean;
20
23
  }
21
24
  export interface CiCommandConfig {
22
25
  readonly command: string;
@@ -32,5 +35,9 @@ export declare function registerCiCommand(cli: CAC): void;
32
35
  export declare function buildCiActCommand(options?: CiActOptions, cwd?: string): CiCommandConfig;
33
36
  export declare function validateCiActCommand(..._legacyArgs: readonly unknown[]): string | null;
34
37
  export declare function runCiActCommand(options?: CiActOptions, deps?: CiCommandDeps): Promise<number>;
35
- export declare function normalizeCiActTimeoutMs(value: number | undefined): number;
38
+ export declare function normalizeCiActTimeoutMs(value: number | undefined, options?: {
39
+ readonly smoke?: boolean;
40
+ }): number;
36
41
  export declare function parseCiActTimeoutMs(value: unknown): number | undefined;
42
+ export declare function parseCiActExecutionMode(value: unknown): CiActExecutionMode | undefined;
43
+ export declare function parseCiActEventName(value: unknown): CiActEventName | undefined;