@webpresso/agent-kit 0.21.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 (1230) hide show
  1. package/.claude-plugin/marketplace.json +27 -0
  2. package/.claude-plugin/plugin.json +73 -0
  3. package/LICENSE +21 -0
  4. package/README.md +106 -0
  5. package/THIRD-PARTY-NOTICES.md +60 -0
  6. package/bin/_run.js +201 -0
  7. package/bin/docs-check-internal-links.js +5 -0
  8. package/bin/docs-check-refs.js +5 -0
  9. package/bin/docs-check-stale.js +5 -0
  10. package/bin/docs-lint.js +5 -0
  11. package/bin/docs-migrate.js +5 -0
  12. package/bin/wp-check-dev-link.js +5 -0
  13. package/bin/wp-guard-switch.js +5 -0
  14. package/bin/wp-post-tool.js +5 -0
  15. package/bin/wp-pretool-guard.js +5 -0
  16. package/bin/wp-restore-dev-links.js +5 -0
  17. package/bin/wp-sessionstart-routing.js +5 -0
  18. package/bin/wp-stop-qa.js +5 -0
  19. package/bin/wp-test-quality-check.js +5 -0
  20. package/bin/wp.js +5 -0
  21. package/catalog/AGENTS.md.tpl +202 -0
  22. package/catalog/agent/.audit-budgets.yaml +12 -0
  23. package/catalog/agent/agents/README.md +22 -0
  24. package/catalog/agent/agents/code-reviewer.md +34 -0
  25. package/catalog/agent/agents/doc-writer.md +35 -0
  26. package/catalog/agent/agents/explorer.md +33 -0
  27. package/catalog/agent/agents/security-auditor.md +34 -0
  28. package/catalog/agent/commands/audit-duplication.md +34 -0
  29. package/catalog/agent/commands/audit.md +219 -0
  30. package/catalog/agent/commands/brainstorm.md +115 -0
  31. package/catalog/agent/commands/decide.md +132 -0
  32. package/catalog/agent/commands/fix-all.md +160 -0
  33. package/catalog/agent/commands/fix.md +109 -0
  34. package/catalog/agent/commands/plan-refine.md +103 -0
  35. package/catalog/agent/commands/pll.md +174 -0
  36. package/catalog/agent/commands/tph.md +380 -0
  37. package/catalog/agent/commands/verify.md +9 -0
  38. package/catalog/agent/correlate.allow.yaml +5 -0
  39. package/catalog/agent/guides/agent-guardrails.md +116 -0
  40. package/catalog/agent/guides/parallel-execution.md +79 -0
  41. package/catalog/agent/guides/plan-audit-checklist.md +189 -0
  42. package/catalog/agent/guides/skills.md +32 -0
  43. package/catalog/agent/rules/README.md +30 -0
  44. package/catalog/agent/rules/agent-guide.md +464 -0
  45. package/catalog/agent/rules/blueprint-scoping.md +69 -0
  46. package/catalog/agent/rules/changeset-release.md +161 -0
  47. package/catalog/agent/rules/cmd-execution.md +121 -0
  48. package/catalog/agent/rules/context-mode-routing.md +64 -0
  49. package/catalog/agent/rules/engineering-principles.md +42 -0
  50. package/catalog/agent/rules/extraction-parity.md +157 -0
  51. package/catalog/agent/rules/generated-code-governance.md +87 -0
  52. package/catalog/agent/rules/gstack-routing.md +90 -0
  53. package/catalog/agent/rules/no-timeout-as-fix.md +90 -0
  54. package/catalog/agent/rules/package-conventions.md +80 -0
  55. package/catalog/agent/rules/pre-implementation.md +44 -0
  56. package/catalog/agent/rules/public-package-safety.md +56 -0
  57. package/catalog/agent/rules/repo-restrictions.md +175 -0
  58. package/catalog/agent/rules/rtk-routing.md +50 -0
  59. package/catalog/agent/rules/supported-agent-clis.md +80 -0
  60. package/catalog/agent/rules/ts-coding-conventions.md +68 -0
  61. package/catalog/agent/skills/better-auth-best-practices/SKILL.md +212 -0
  62. package/catalog/agent/skills/deep-research/SKILL.md +240 -0
  63. package/catalog/agent/skills/fix/SKILL.md +120 -0
  64. package/catalog/agent/skills/frontend-design/LICENSE.txt +177 -0
  65. package/catalog/agent/skills/frontend-design/SKILL.md +189 -0
  66. package/catalog/agent/skills/hooks-doctor/SKILL.md +77 -0
  67. package/catalog/agent/skills/logging-best-practices/SKILL.md +145 -0
  68. package/catalog/agent/skills/logging-best-practices/rules/context.md +157 -0
  69. package/catalog/agent/skills/logging-best-practices/rules/pitfalls.md +118 -0
  70. package/catalog/agent/skills/logging-best-practices/rules/structure.md +195 -0
  71. package/catalog/agent/skills/logging-best-practices/rules/wide-events.md +113 -0
  72. package/catalog/agent/skills/lore-protocol/SKILL.md +93 -0
  73. package/catalog/agent/skills/monorepo-navigation/SKILL.md.tpl +57 -0
  74. package/catalog/agent/skills/monorepo-navigation/examples/webpresso.md +240 -0
  75. package/catalog/agent/skills/plan-refine/SKILL.md +645 -0
  76. package/catalog/agent/skills/pll/SKILL.md +85 -0
  77. package/catalog/agent/skills/react-doctor/SKILL.md +54 -0
  78. package/catalog/agent/skills/systematic-debugging/CREATION-LOG.md +133 -0
  79. package/catalog/agent/skills/systematic-debugging/SKILL.md +322 -0
  80. package/catalog/agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  81. package/catalog/agent/skills/systematic-debugging/condition-based-waiting.md +120 -0
  82. package/catalog/agent/skills/systematic-debugging/defense-in-depth.md +128 -0
  83. package/catalog/agent/skills/systematic-debugging/find-polluter.sh +63 -0
  84. package/catalog/agent/skills/systematic-debugging/root-cause-tracing.md +183 -0
  85. package/catalog/agent/skills/systematic-debugging/test-academic.md +14 -0
  86. package/catalog/agent/skills/systematic-debugging/test-pressure-1.md +65 -0
  87. package/catalog/agent/skills/systematic-debugging/test-pressure-2.md +75 -0
  88. package/catalog/agent/skills/systematic-debugging/test-pressure-3.md +75 -0
  89. package/catalog/agent/skills/tanstack-query/.claude-plugin/plugin.json +12 -0
  90. package/catalog/agent/skills/tanstack-query/README.md +59 -0
  91. package/catalog/agent/skills/tanstack-query/SKILL.md +175 -0
  92. package/catalog/agent/skills/tanstack-query/references/best-practices.md +63 -0
  93. package/catalog/agent/skills/tanstack-query/references/common-patterns.md +43 -0
  94. package/catalog/agent/skills/tanstack-query/references/testing.md +44 -0
  95. package/catalog/agent/skills/tanstack-query/references/top-errors.md +19 -0
  96. package/catalog/agent/skills/tanstack-query/references/typescript-patterns.md +36 -0
  97. package/catalog/agent/skills/tanstack-query/rules/tanstack-query.md +41 -0
  98. package/catalog/agent/skills/tanstack-query/templates/custom-hooks-pattern.tsx +26 -0
  99. package/catalog/agent/skills/tanstack-query/templates/devtools-setup.tsx +13 -0
  100. package/catalog/agent/skills/tanstack-query/templates/error-boundary.tsx +52 -0
  101. package/catalog/agent/skills/tanstack-query/templates/package.json +24 -0
  102. package/catalog/agent/skills/tanstack-query/templates/provider-setup.tsx +19 -0
  103. package/catalog/agent/skills/tanstack-query/templates/query-client-config.ts +43 -0
  104. package/catalog/agent/skills/tanstack-query/templates/use-infinite-query.tsx +61 -0
  105. package/catalog/agent/skills/tanstack-query/templates/use-mutation-basic.tsx +52 -0
  106. package/catalog/agent/skills/tanstack-query/templates/use-mutation-optimistic.tsx +48 -0
  107. package/catalog/agent/skills/tanstack-query/templates/use-query-basic.tsx +77 -0
  108. package/catalog/agent/skills/tech-debt/SKILL.md +79 -0
  109. package/catalog/agent/skills/test-driven-development/SKILL.md +403 -0
  110. package/catalog/agent/skills/test-driven-development/testing-anti-patterns.md +317 -0
  111. package/catalog/agent/skills/testing-philosophy/SKILL.md +530 -0
  112. package/catalog/agent/skills/third-party-manifest.json +30 -0
  113. package/catalog/agent/skills/vercel-react-best-practices/AGENTS.md +2672 -0
  114. package/catalog/agent/skills/vercel-react-best-practices/README.md +127 -0
  115. package/catalog/agent/skills/vercel-react-best-practices/SKILL.md +212 -0
  116. package/catalog/agent/skills/vercel-react-best-practices/metadata.json +15 -0
  117. package/catalog/agent/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  118. package/catalog/agent/skills/vercel-react-best-practices/rules/_template.md +28 -0
  119. package/catalog/agent/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  120. package/catalog/agent/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  121. package/catalog/agent/skills/vercel-react-best-practices/rules/async-api-routes.md +35 -0
  122. package/catalog/agent/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  123. package/catalog/agent/skills/vercel-react-best-practices/rules/async-dependencies.md +48 -0
  124. package/catalog/agent/skills/vercel-react-best-practices/rules/async-parallel.md +24 -0
  125. package/catalog/agent/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  126. package/catalog/agent/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  127. package/catalog/agent/skills/vercel-react-best-practices/rules/bundle-conditional.md +37 -0
  128. package/catalog/agent/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +48 -0
  129. package/catalog/agent/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +34 -0
  130. package/catalog/agent/skills/vercel-react-best-practices/rules/bundle-preload.md +44 -0
  131. package/catalog/agent/skills/vercel-react-best-practices/rules/client-event-listeners.md +78 -0
  132. package/catalog/agent/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +74 -0
  133. package/catalog/agent/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  134. package/catalog/agent/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  135. package/catalog/agent/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +110 -0
  136. package/catalog/agent/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  137. package/catalog/agent/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  138. package/catalog/agent/skills/vercel-react-best-practices/rules/js-cache-storage.md +68 -0
  139. package/catalog/agent/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  140. package/catalog/agent/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  141. package/catalog/agent/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  142. package/catalog/agent/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  143. package/catalog/agent/skills/vercel-react-best-practices/rules/js-length-check-first.md +50 -0
  144. package/catalog/agent/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  145. package/catalog/agent/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  146. package/catalog/agent/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  147. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  148. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  149. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +32 -0
  150. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  151. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  152. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +72 -0
  153. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  154. package/catalog/agent/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  155. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  156. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  157. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  158. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +77 -0
  159. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  160. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  161. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  162. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  163. package/catalog/agent/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  164. package/catalog/agent/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  165. package/catalog/agent/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  166. package/catalog/agent/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  167. package/catalog/agent/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  168. package/catalog/agent/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  169. package/catalog/agent/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  170. package/catalog/agent/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  171. package/catalog/agent/skills/verify/SKILL.md +133 -0
  172. package/catalog/agent/skills/web-design-guidelines/SKILL.md +53 -0
  173. package/catalog/agent/workflows/README.md +20 -0
  174. package/catalog/agent/workflows/conf.md +18 -0
  175. package/catalog/agent/workflows/debug.md +20 -0
  176. package/catalog/agent/workflows/docs.md +9 -0
  177. package/catalog/agent/workflows/execute-plan.md +15 -0
  178. package/catalog/agent/workflows/fix-all-md-warnings.md +13 -0
  179. package/catalog/agent/workflows/test.md +14 -0
  180. package/catalog/agent/workflows/write-plan.md +16 -0
  181. package/catalog/base-kit/.actrc.tmpl +2 -0
  182. package/catalog/base-kit/.editorconfig.tmpl +23 -0
  183. package/catalog/base-kit/.github/workflows/ci.webpresso.yml.tmpl +66 -0
  184. package/catalog/base-kit/.gitignore.tmpl +82 -0
  185. package/catalog/base-kit/.husky/commit-msg.tmpl +7 -0
  186. package/catalog/base-kit/.husky/pre-commit.tmpl +10 -0
  187. package/catalog/base-kit/.secretlintrc.json.tmpl +5 -0
  188. package/catalog/base-kit/commitlint.config.ts.tmpl +7 -0
  189. package/catalog/base-kit/e2e/.gitkeep.tmpl +0 -0
  190. package/catalog/base-kit/pnpm-workspace.yaml.tmpl +49 -0
  191. package/catalog/base-kit/scripts/audit-secret-provider-quarantine.ts.tmpl +91 -0
  192. package/catalog/base-kit/scripts/check-no-dev-vars.ts.tmpl +56 -0
  193. package/catalog/base-kit/test/.gitkeep.tmpl +0 -0
  194. package/catalog/blueprints/archived/.gitkeep +0 -0
  195. package/catalog/blueprints/completed/.gitkeep +0 -0
  196. package/catalog/blueprints/in-progress/.gitkeep +0 -0
  197. package/catalog/blueprints/parked/.gitkeep +0 -0
  198. package/catalog/blueprints/planned/.gitkeep +0 -0
  199. package/catalog/docs/templates/adr.md +38 -0
  200. package/catalog/docs/templates/blueprint.md +149 -0
  201. package/catalog/docs/templates/blueprint.yaml +110 -0
  202. package/catalog/docs/templates/core-doc.yaml +28 -0
  203. package/catalog/docs/templates/guide.md +31 -0
  204. package/catalog/docs/templates/guide.yaml +31 -0
  205. package/catalog/docs/templates/postmortem.md +60 -0
  206. package/catalog/docs/templates/research.md +37 -0
  207. package/catalog/docs/templates/runbook.md +39 -0
  208. package/catalog/docs/templates/system.md +44 -0
  209. package/catalog/docs/templates/tech-debt.md +78 -0
  210. package/catalog/vision/VISION.md.tmpl +33 -0
  211. package/commands/audit.md +13 -0
  212. package/commands/blueprint.md +28 -0
  213. package/commands/qa.md +4 -0
  214. package/commands/test.md +4 -0
  215. package/dist/esm/ai-memory/checkpoint/saver.d.ts +14 -0
  216. package/dist/esm/ai-memory/checkpoint/saver.js +28 -0
  217. package/dist/esm/ai-memory/checkpoint/types.d.ts +75 -0
  218. package/dist/esm/ai-memory/checkpoint/types.js +2 -0
  219. package/dist/esm/ai-memory/facts/consolidator.d.ts +23 -0
  220. package/dist/esm/ai-memory/facts/consolidator.js +134 -0
  221. package/dist/esm/ai-memory/facts/extractor.d.ts +28 -0
  222. package/dist/esm/ai-memory/facts/extractor.js +119 -0
  223. package/dist/esm/ai-memory/facts/types.d.ts +61 -0
  224. package/dist/esm/ai-memory/facts/types.js +2 -0
  225. package/dist/esm/ai-memory/hierarchy/retriever.d.ts +47 -0
  226. package/dist/esm/ai-memory/hierarchy/retriever.js +139 -0
  227. package/dist/esm/ai-memory/index.d.ts +11 -0
  228. package/dist/esm/ai-memory/index.js +6 -0
  229. package/dist/esm/ai-memory/store/sqlite-store.d.ts +28 -0
  230. package/dist/esm/ai-memory/store/sqlite-store.js +213 -0
  231. package/dist/esm/ai-prompts/business-canvas.d.ts +52 -0
  232. package/dist/esm/ai-prompts/business-canvas.js +292 -0
  233. package/dist/esm/ai-prompts/circuit-breaker.d.ts +35 -0
  234. package/dist/esm/ai-prompts/circuit-breaker.js +171 -0
  235. package/dist/esm/ai-prompts/experiment-draft.d.ts +86 -0
  236. package/dist/esm/ai-prompts/experiment-draft.js +188 -0
  237. package/dist/esm/ai-prompts/index.d.ts +12 -0
  238. package/dist/esm/ai-prompts/index.js +11 -0
  239. package/dist/esm/ai-prompts/persona-context.d.ts +70 -0
  240. package/dist/esm/ai-prompts/persona-context.js +158 -0
  241. package/dist/esm/ai-prompts/persona-debate.d.ts +67 -0
  242. package/dist/esm/ai-prompts/persona-debate.js +172 -0
  243. package/dist/esm/ai-prompts/persona-tools.d.ts +26 -0
  244. package/dist/esm/ai-prompts/persona-tools.js +172 -0
  245. package/dist/esm/ai-prompts/personas.d.ts +16 -0
  246. package/dist/esm/ai-prompts/personas.js +492 -0
  247. package/dist/esm/ai-prompts/rachel-planning.d.ts +28 -0
  248. package/dist/esm/ai-prompts/rachel-planning.js +217 -0
  249. package/dist/esm/ai-prompts/task-analysis.d.ts +49 -0
  250. package/dist/esm/ai-prompts/task-analysis.js +434 -0
  251. package/dist/esm/ai-prompts/types.d.ts +3 -0
  252. package/dist/esm/ai-prompts/types.js +2 -0
  253. package/dist/esm/ai-tools/index.d.ts +7 -0
  254. package/dist/esm/ai-tools/index.js +6 -0
  255. package/dist/esm/ai-tools/list-files.d.ts +3 -0
  256. package/dist/esm/ai-tools/list-files.js +93 -0
  257. package/dist/esm/ai-tools/read-file.d.ts +3 -0
  258. package/dist/esm/ai-tools/read-file.js +108 -0
  259. package/dist/esm/ai-tools/search-files.d.ts +3 -0
  260. package/dist/esm/ai-tools/search-files.js +166 -0
  261. package/dist/esm/ai-tools/shared/validate-path.d.ts +11 -0
  262. package/dist/esm/ai-tools/shared/validate-path.js +25 -0
  263. package/dist/esm/ai-tools/types.d.ts +370 -0
  264. package/dist/esm/ai-tools/types.js +2 -0
  265. package/dist/esm/ai-tools/write-file.d.ts +3 -0
  266. package/dist/esm/ai-tools/write-file.js +165 -0
  267. package/dist/esm/audit/_budgets.d.ts +28 -0
  268. package/dist/esm/audit/_budgets.js +60 -0
  269. package/dist/esm/audit/absolute-path-policy.d.ts +5 -0
  270. package/dist/esm/audit/absolute-path-policy.js +97 -0
  271. package/dist/esm/audit/agent-cost.d.ts +3 -0
  272. package/dist/esm/audit/agent-cost.js +111 -0
  273. package/dist/esm/audit/agents.d.ts +3 -0
  274. package/dist/esm/audit/agents.js +331 -0
  275. package/dist/esm/audit/ai-contracts.d.ts +3 -0
  276. package/dist/esm/audit/ai-contracts.js +238 -0
  277. package/dist/esm/audit/architecture-drift.d.ts +33 -0
  278. package/dist/esm/audit/architecture-drift.js +364 -0
  279. package/dist/esm/audit/audit-mutation-score.d.ts +43 -0
  280. package/dist/esm/audit/audit-mutation-score.js +92 -0
  281. package/dist/esm/audit/audit-no-ambient-root.d.ts +29 -0
  282. package/dist/esm/audit/audit-no-ambient-root.js +83 -0
  283. package/dist/esm/audit/audit-tph-detect.d.ts +49 -0
  284. package/dist/esm/audit/audit-tph-detect.js +248 -0
  285. package/dist/esm/audit/audit-tph-e2e-detect.d.ts +27 -0
  286. package/dist/esm/audit/audit-tph-e2e-detect.js +84 -0
  287. package/dist/esm/audit/audit-tph-e2e-runner.d.ts +8 -0
  288. package/dist/esm/audit/audit-tph-e2e-runner.js +106 -0
  289. package/dist/esm/audit/audit-tph-e2e.d.ts +16 -0
  290. package/dist/esm/audit/audit-tph-e2e.js +17 -0
  291. package/dist/esm/audit/audit-tph-runner.d.ts +10 -0
  292. package/dist/esm/audit/audit-tph-runner.js +115 -0
  293. package/dist/esm/audit/audit-tph.d.ts +17 -0
  294. package/dist/esm/audit/audit-tph.js +38 -0
  295. package/dist/esm/audit/blueprint-db-consistency.d.ts +15 -0
  296. package/dist/esm/audit/blueprint-db-consistency.js +109 -0
  297. package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +17 -0
  298. package/dist/esm/audit/blueprint-lifecycle-sql.js +136 -0
  299. package/dist/esm/audit/broken-refs.d.ts +26 -0
  300. package/dist/esm/audit/broken-refs.js +181 -0
  301. package/dist/esm/audit/bucket-boundary.d.ts +21 -0
  302. package/dist/esm/audit/bucket-boundary.js +330 -0
  303. package/dist/esm/audit/commit-message-lore.d.ts +41 -0
  304. package/dist/esm/audit/commit-message-lore.js +113 -0
  305. package/dist/esm/audit/compile-drift.d.ts +3 -0
  306. package/dist/esm/audit/compile-drift.js +42 -0
  307. package/dist/esm/audit/cross-repo-correlation.d.ts +14 -0
  308. package/dist/esm/audit/cross-repo-correlation.js +50 -0
  309. package/dist/esm/audit/gitignore-agent-surfaces.d.ts +3 -0
  310. package/dist/esm/audit/gitignore-agent-surfaces.js +68 -0
  311. package/dist/esm/audit/hook-surface.d.ts +82 -0
  312. package/dist/esm/audit/hook-surface.js +251 -0
  313. package/dist/esm/audit/memory-rotation.d.ts +31 -0
  314. package/dist/esm/audit/memory-rotation.js +137 -0
  315. package/dist/esm/audit/memory-unified.d.ts +3 -0
  316. package/dist/esm/audit/memory-unified.js +46 -0
  317. package/dist/esm/audit/open-source-licenses.d.ts +4 -0
  318. package/dist/esm/audit/open-source-licenses.js +224 -0
  319. package/dist/esm/audit/package-surface.d.ts +7 -0
  320. package/dist/esm/audit/package-surface.js +674 -0
  321. package/dist/esm/audit/repo-guardrails.d.ts +89 -0
  322. package/dist/esm/audit/repo-guardrails.js +875 -0
  323. package/dist/esm/audit/roadmap-links.d.ts +7 -0
  324. package/dist/esm/audit/roadmap-links.js +235 -0
  325. package/dist/esm/audit/run-stryker.d.ts +9 -0
  326. package/dist/esm/audit/run-stryker.js +24 -0
  327. package/dist/esm/audit/shell.d.ts +17 -0
  328. package/dist/esm/audit/shell.js +32 -0
  329. package/dist/esm/audit/skill-sizes.d.ts +25 -0
  330. package/dist/esm/audit/skill-sizes.js +153 -0
  331. package/dist/esm/audit/tech-debt-cadence.d.ts +16 -0
  332. package/dist/esm/audit/tech-debt-cadence.js +101 -0
  333. package/dist/esm/audit/tech-debt.d.ts +9 -0
  334. package/dist/esm/audit/tech-debt.js +107 -0
  335. package/dist/esm/audit/vision-doc.d.ts +21 -0
  336. package/dist/esm/audit/vision-doc.js +136 -0
  337. package/dist/esm/blueprint/aggregate.d.ts +146 -0
  338. package/dist/esm/blueprint/aggregate.js +217 -0
  339. package/dist/esm/blueprint/context.d.ts +70 -0
  340. package/dist/esm/blueprint/context.js +301 -0
  341. package/dist/esm/blueprint/core/parser.d.ts +53 -0
  342. package/dist/esm/blueprint/core/parser.js +281 -0
  343. package/dist/esm/blueprint/core/schema.d.ts +163 -0
  344. package/dist/esm/blueprint/core/schema.js +98 -0
  345. package/dist/esm/blueprint/core/types.d.ts +13 -0
  346. package/dist/esm/blueprint/core/types.js +5 -0
  347. package/dist/esm/blueprint/core/validation/criteria.d.ts +6 -0
  348. package/dist/esm/blueprint/core/validation/criteria.js +15 -0
  349. package/dist/esm/blueprint/core/validation/dependencies.d.ts +19 -0
  350. package/dist/esm/blueprint/core/validation/dependencies.js +113 -0
  351. package/dist/esm/blueprint/core/validation/index.d.ts +13 -0
  352. package/dist/esm/blueprint/core/validation/index.js +11 -0
  353. package/dist/esm/blueprint/core/validation/links.d.ts +18 -0
  354. package/dist/esm/blueprint/core/validation/links.js +47 -0
  355. package/dist/esm/blueprint/core/validation/phases.d.ts +12 -0
  356. package/dist/esm/blueprint/core/validation/phases.js +18 -0
  357. package/dist/esm/blueprint/core/validation/state.d.ts +9 -0
  358. package/dist/esm/blueprint/core/validation/state.js +123 -0
  359. package/dist/esm/blueprint/core/validation/task-blocks.d.ts +27 -0
  360. package/dist/esm/blueprint/core/validation/task-blocks.js +48 -0
  361. package/dist/esm/blueprint/core/validation/task-sections.d.ts +14 -0
  362. package/dist/esm/blueprint/core/validation/task-sections.js +60 -0
  363. package/dist/esm/blueprint/core/validation/template.d.ts +9 -0
  364. package/dist/esm/blueprint/core/validation/template.js +65 -0
  365. package/dist/esm/blueprint/cross-repo/allowlist.d.ts +28 -0
  366. package/dist/esm/blueprint/cross-repo/allowlist.js +87 -0
  367. package/dist/esm/blueprint/cross-repo/audit.d.ts +49 -0
  368. package/dist/esm/blueprint/cross-repo/audit.js +161 -0
  369. package/dist/esm/blueprint/cross-repo/resolver.d.ts +28 -0
  370. package/dist/esm/blueprint/cross-repo/resolver.js +32 -0
  371. package/dist/esm/blueprint/dag/cycle-detector.d.ts +12 -0
  372. package/dist/esm/blueprint/dag/cycle-detector.js +46 -0
  373. package/dist/esm/blueprint/dag/executor.d.ts +140 -0
  374. package/dist/esm/blueprint/dag/executor.js +292 -0
  375. package/dist/esm/blueprint/dag/index.d.ts +20 -0
  376. package/dist/esm/blueprint/dag/index.js +17 -0
  377. package/dist/esm/blueprint/dag/interfaces.d.ts +56 -0
  378. package/dist/esm/blueprint/dag/interfaces.js +13 -0
  379. package/dist/esm/blueprint/dag/local/independence.d.ts +107 -0
  380. package/dist/esm/blueprint/dag/local/independence.js +231 -0
  381. package/dist/esm/blueprint/dag/local/index.d.ts +14 -0
  382. package/dist/esm/blueprint/dag/local/index.js +14 -0
  383. package/dist/esm/blueprint/dag/local/package-graph.d.ts +66 -0
  384. package/dist/esm/blueprint/dag/local/package-graph.js +148 -0
  385. package/dist/esm/blueprint/dag/plan-parser.d.ts +54 -0
  386. package/dist/esm/blueprint/dag/plan-parser.js +236 -0
  387. package/dist/esm/blueprint/dag/task-graph-algorithms.d.ts +13 -0
  388. package/dist/esm/blueprint/dag/task-graph-algorithms.js +236 -0
  389. package/dist/esm/blueprint/dag/task-graph.d.ts +171 -0
  390. package/dist/esm/blueprint/dag/task-graph.js +370 -0
  391. package/dist/esm/blueprint/dag/types.d.ts +17 -0
  392. package/dist/esm/blueprint/dag/types.js +2 -0
  393. package/dist/esm/blueprint/db/cold-start.d.ts +8 -0
  394. package/dist/esm/blueprint/db/cold-start.js +45 -0
  395. package/dist/esm/blueprint/db/connection.d.ts +8 -0
  396. package/dist/esm/blueprint/db/connection.js +45 -0
  397. package/dist/esm/blueprint/db/enums.d.ts +76 -0
  398. package/dist/esm/blueprint/db/enums.js +37 -0
  399. package/dist/esm/blueprint/db/ingester.d.ts +25 -0
  400. package/dist/esm/blueprint/db/ingester.js +307 -0
  401. package/dist/esm/blueprint/db/legacy-migration.d.ts +41 -0
  402. package/dist/esm/blueprint/db/legacy-migration.js +122 -0
  403. package/dist/esm/blueprint/db/migrations/run.d.ts +3 -0
  404. package/dist/esm/blueprint/db/migrations/run.js +53 -0
  405. package/dist/esm/blueprint/db/parser/blueprint-db-parser.d.ts +69 -0
  406. package/dist/esm/blueprint/db/parser/blueprint-db-parser.js +408 -0
  407. package/dist/esm/blueprint/db/parser/tech-debt-db-parser.d.ts +33 -0
  408. package/dist/esm/blueprint/db/parser/tech-debt-db-parser.js +134 -0
  409. package/dist/esm/blueprint/db/paths.d.ts +104 -0
  410. package/dist/esm/blueprint/db/paths.js +192 -0
  411. package/dist/esm/blueprint/db/sqlite.d.ts +32 -0
  412. package/dist/esm/blueprint/db/sqlite.js +46 -0
  413. package/dist/esm/blueprint/db/template-runner.d.ts +8 -0
  414. package/dist/esm/blueprint/db/template-runner.js +65 -0
  415. package/dist/esm/blueprint/db/templates.d.ts +11 -0
  416. package/dist/esm/blueprint/db/templates.js +226 -0
  417. package/dist/esm/blueprint/db/workspace-config.d.ts +38 -0
  418. package/dist/esm/blueprint/db/workspace-config.js +150 -0
  419. package/dist/esm/blueprint/evidence.d.ts +140 -0
  420. package/dist/esm/blueprint/evidence.js +152 -0
  421. package/dist/esm/blueprint/execution/artifacts.d.ts +9 -0
  422. package/dist/esm/blueprint/execution/artifacts.js +45 -0
  423. package/dist/esm/blueprint/execution/metadata.d.ts +11 -0
  424. package/dist/esm/blueprint/execution/metadata.js +46 -0
  425. package/dist/esm/blueprint/execution/progress-bridge.d.ts +117 -0
  426. package/dist/esm/blueprint/execution/progress-bridge.js +302 -0
  427. package/dist/esm/blueprint/execution/types.d.ts +233 -0
  428. package/dist/esm/blueprint/execution/types.js +99 -0
  429. package/dist/esm/blueprint/export/spec-kit/_field-map.d.ts +12 -0
  430. package/dist/esm/blueprint/export/spec-kit/_field-map.js +33 -0
  431. package/dist/esm/blueprint/export/spec-kit/constitution.d.ts +7 -0
  432. package/dist/esm/blueprint/export/spec-kit/constitution.js +61 -0
  433. package/dist/esm/blueprint/export/spec-kit/index.d.ts +13 -0
  434. package/dist/esm/blueprint/export/spec-kit/index.js +17 -0
  435. package/dist/esm/blueprint/export/spec-kit/plan.d.ts +7 -0
  436. package/dist/esm/blueprint/export/spec-kit/plan.js +43 -0
  437. package/dist/esm/blueprint/export/spec-kit/spec.d.ts +7 -0
  438. package/dist/esm/blueprint/export/spec-kit/spec.js +35 -0
  439. package/dist/esm/blueprint/export/spec-kit/tasks.d.ts +3 -0
  440. package/dist/esm/blueprint/export/spec-kit/tasks.js +32 -0
  441. package/dist/esm/blueprint/freshness.d.ts +78 -0
  442. package/dist/esm/blueprint/freshness.js +127 -0
  443. package/dist/esm/blueprint/graph/index.d.ts +5 -0
  444. package/dist/esm/blueprint/graph/index.js +5 -0
  445. package/dist/esm/blueprint/graph/mermaid-parser.d.ts +3 -0
  446. package/dist/esm/blueprint/graph/mermaid-parser.js +93 -0
  447. package/dist/esm/blueprint/graph/mermaid-serializer.d.ts +3 -0
  448. package/dist/esm/blueprint/graph/mermaid-serializer.js +20 -0
  449. package/dist/esm/blueprint/graph/schema.d.ts +89 -0
  450. package/dist/esm/blueprint/graph/schema.js +104 -0
  451. package/dist/esm/blueprint/graph/task-graph-adapter.d.ts +6 -0
  452. package/dist/esm/blueprint/graph/task-graph-adapter.js +30 -0
  453. package/dist/esm/blueprint/history/diff.d.ts +36 -0
  454. package/dist/esm/blueprint/history/diff.js +122 -0
  455. package/dist/esm/blueprint/index.d.ts +37 -0
  456. package/dist/esm/blueprint/index.js +46 -0
  457. package/dist/esm/blueprint/lifecycle/audit.d.ts +17 -0
  458. package/dist/esm/blueprint/lifecycle/audit.js +423 -0
  459. package/dist/esm/blueprint/lifecycle/engine.d.ts +38 -0
  460. package/dist/esm/blueprint/lifecycle/engine.js +157 -0
  461. package/dist/esm/blueprint/lifecycle/local.d.ts +15 -0
  462. package/dist/esm/blueprint/lifecycle/local.js +92 -0
  463. package/dist/esm/blueprint/local.d.ts +21 -0
  464. package/dist/esm/blueprint/local.js +25 -0
  465. package/dist/esm/blueprint/markdown/helpers.d.ts +17 -0
  466. package/dist/esm/blueprint/markdown/helpers.js +92 -0
  467. package/dist/esm/blueprint/markdown/task-heading.d.ts +8 -0
  468. package/dist/esm/blueprint/markdown/task-heading.js +19 -0
  469. package/dist/esm/blueprint/next-action.d.ts +27 -0
  470. package/dist/esm/blueprint/next-action.js +45 -0
  471. package/dist/esm/blueprint/project-resolver.d.ts +31 -0
  472. package/dist/esm/blueprint/project-resolver.js +142 -0
  473. package/dist/esm/blueprint/projection-ready.d.ts +3 -0
  474. package/dist/esm/blueprint/projection-ready.js +29 -0
  475. package/dist/esm/blueprint/projects.d.ts +96 -0
  476. package/dist/esm/blueprint/projects.js +383 -0
  477. package/dist/esm/blueprint/query/types.d.ts +53 -0
  478. package/dist/esm/blueprint/query/types.js +16 -0
  479. package/dist/esm/blueprint/roadmap.d.ts +24 -0
  480. package/dist/esm/blueprint/roadmap.js +82 -0
  481. package/dist/esm/blueprint/service/BlueprintCreationService.d.ts +47 -0
  482. package/dist/esm/blueprint/service/BlueprintCreationService.js +260 -0
  483. package/dist/esm/blueprint/service/BlueprintService.d.ts +70 -0
  484. package/dist/esm/blueprint/service/BlueprintService.js +190 -0
  485. package/dist/esm/blueprint/service/TechDebtService.d.ts +102 -0
  486. package/dist/esm/blueprint/service/TechDebtService.js +337 -0
  487. package/dist/esm/blueprint/service/TrackedDocumentService.d.ts +198 -0
  488. package/dist/esm/blueprint/service/TrackedDocumentService.js +162 -0
  489. package/dist/esm/blueprint/service/blueprint-records.d.ts +8 -0
  490. package/dist/esm/blueprint/service/blueprint-records.js +124 -0
  491. package/dist/esm/blueprint/service/blueprint-tech-debt-links.d.ts +3 -0
  492. package/dist/esm/blueprint/service/blueprint-tech-debt-links.js +35 -0
  493. package/dist/esm/blueprint/service/priority-scoring.d.ts +21 -0
  494. package/dist/esm/blueprint/service/priority-scoring.js +85 -0
  495. package/dist/esm/blueprint/service/scanner.d.ts +56 -0
  496. package/dist/esm/blueprint/service/scanner.js +212 -0
  497. package/dist/esm/blueprint/sync/auth.d.ts +27 -0
  498. package/dist/esm/blueprint/sync/auth.js +59 -0
  499. package/dist/esm/blueprint/sync/client.d.ts +64 -0
  500. package/dist/esm/blueprint/sync/client.js +232 -0
  501. package/dist/esm/blueprint/sync/replica.d.ts +55 -0
  502. package/dist/esm/blueprint/sync/replica.js +139 -0
  503. package/dist/esm/blueprint/sync/types.d.ts +178 -0
  504. package/dist/esm/blueprint/sync/types.js +18 -0
  505. package/dist/esm/blueprint/tech-debt/index.d.ts +9 -0
  506. package/dist/esm/blueprint/tech-debt/index.js +9 -0
  507. package/dist/esm/blueprint/tech-debt/parser.d.ts +56 -0
  508. package/dist/esm/blueprint/tech-debt/parser.js +133 -0
  509. package/dist/esm/blueprint/tech-debt/query-types.d.ts +130 -0
  510. package/dist/esm/blueprint/tech-debt/query-types.js +37 -0
  511. package/dist/esm/blueprint/tech-debt/schema.d.ts +151 -0
  512. package/dist/esm/blueprint/tech-debt/schema.js +145 -0
  513. package/dist/esm/blueprint/test-utils/blueprint-mocks.d.ts +31 -0
  514. package/dist/esm/blueprint/test-utils/blueprint-mocks.js +63 -0
  515. package/dist/esm/blueprint/tracked-document/index.d.ts +11 -0
  516. package/dist/esm/blueprint/tracked-document/index.js +11 -0
  517. package/dist/esm/blueprint/tracked-document/parser.d.ts +113 -0
  518. package/dist/esm/blueprint/tracked-document/parser.js +197 -0
  519. package/dist/esm/blueprint/tracked-document/query-types.d.ts +43 -0
  520. package/dist/esm/blueprint/tracked-document/query-types.js +8 -0
  521. package/dist/esm/blueprint/tracked-document/schema.d.ts +80 -0
  522. package/dist/esm/blueprint/tracked-document/schema.js +89 -0
  523. package/dist/esm/blueprint/types/execution-backend.d.ts +17 -0
  524. package/dist/esm/blueprint/types/execution-backend.js +16 -0
  525. package/dist/esm/blueprint/utils/archive.d.ts +69 -0
  526. package/dist/esm/blueprint/utils/archive.js +209 -0
  527. package/dist/esm/blueprint/utils/blueprint-root.d.ts +9 -0
  528. package/dist/esm/blueprint/utils/blueprint-root.js +77 -0
  529. package/dist/esm/blueprint/utils/conflict.d.ts +125 -0
  530. package/dist/esm/blueprint/utils/conflict.js +111 -0
  531. package/dist/esm/blueprint/utils/decision-trace-artifacts.d.ts +16 -0
  532. package/dist/esm/blueprint/utils/decision-trace-artifacts.js +37 -0
  533. package/dist/esm/blueprint/utils/errors.d.ts +14 -0
  534. package/dist/esm/blueprint/utils/errors.js +44 -0
  535. package/dist/esm/blueprint/utils/freshness.d.ts +21 -0
  536. package/dist/esm/blueprint/utils/freshness.js +66 -0
  537. package/dist/esm/blueprint/utils/package-assets.d.ts +6 -0
  538. package/dist/esm/blueprint/utils/package-assets.js +20 -0
  539. package/dist/esm/blueprint/utils/string.d.ts +8 -0
  540. package/dist/esm/blueprint/utils/string.js +10 -0
  541. package/dist/esm/blueprint/utils/tech-debt-root.d.ts +4 -0
  542. package/dist/esm/blueprint/utils/tech-debt-root.js +18 -0
  543. package/dist/esm/blueprint/verification.d.ts +116 -0
  544. package/dist/esm/blueprint/verification.js +246 -0
  545. package/dist/esm/build/generate-skills-dir.d.ts +14 -0
  546. package/dist/esm/build/generate-skills-dir.js +56 -0
  547. package/dist/esm/ci/act-helper.d.ts +29 -0
  548. package/dist/esm/ci/act-helper.js +106 -0
  549. package/dist/esm/ci/act-runner.d.ts +24 -0
  550. package/dist/esm/ci/act-runner.js +71 -0
  551. package/dist/esm/cli/auto-update/detect-pm.d.ts +76 -0
  552. package/dist/esm/cli/auto-update/detect-pm.js +237 -0
  553. package/dist/esm/cli/auto-update/installer.d.ts +65 -0
  554. package/dist/esm/cli/auto-update/installer.js +171 -0
  555. package/dist/esm/cli/auto-update/log.d.ts +46 -0
  556. package/dist/esm/cli/auto-update/log.js +107 -0
  557. package/dist/esm/cli/auto-update/run.d.ts +23 -0
  558. package/dist/esm/cli/auto-update/run.js +116 -0
  559. package/dist/esm/cli/auto-update/skip.d.ts +34 -0
  560. package/dist/esm/cli/auto-update/skip.js +84 -0
  561. package/dist/esm/cli/bootstrap.d.ts +28 -0
  562. package/dist/esm/cli/bootstrap.js +55 -0
  563. package/dist/esm/cli/cli.d.ts +11 -0
  564. package/dist/esm/cli/cli.js +310 -0
  565. package/dist/esm/cli/commands/audit-core.d.ts +61 -0
  566. package/dist/esm/cli/commands/audit-core.js +87 -0
  567. package/dist/esm/cli/commands/audit.d.ts +10 -0
  568. package/dist/esm/cli/commands/audit.js +273 -0
  569. package/dist/esm/cli/commands/bench/index.d.ts +6 -0
  570. package/dist/esm/cli/commands/bench/index.js +54 -0
  571. package/dist/esm/cli/commands/bench/session-memory.d.ts +129 -0
  572. package/dist/esm/cli/commands/bench/session-memory.js +242 -0
  573. package/dist/esm/cli/commands/blueprint/db-commands.d.ts +60 -0
  574. package/dist/esm/cli/commands/blueprint/db-commands.js +244 -0
  575. package/dist/esm/cli/commands/blueprint/execution-io.d.ts +80 -0
  576. package/dist/esm/cli/commands/blueprint/execution-io.js +78 -0
  577. package/dist/esm/cli/commands/blueprint/execution-spec.d.ts +45 -0
  578. package/dist/esm/cli/commands/blueprint/execution-spec.js +177 -0
  579. package/dist/esm/cli/commands/blueprint/execution-state.d.ts +17 -0
  580. package/dist/esm/cli/commands/blueprint/execution-state.js +38 -0
  581. package/dist/esm/cli/commands/blueprint/execution.d.ts +74 -0
  582. package/dist/esm/cli/commands/blueprint/execution.js +256 -0
  583. package/dist/esm/cli/commands/blueprint/mutations.d.ts +109 -0
  584. package/dist/esm/cli/commands/blueprint/mutations.js +357 -0
  585. package/dist/esm/cli/commands/blueprint/router-dispatch.d.ts +50 -0
  586. package/dist/esm/cli/commands/blueprint/router-dispatch.js +358 -0
  587. package/dist/esm/cli/commands/blueprint/router-output.d.ts +25 -0
  588. package/dist/esm/cli/commands/blueprint/router-output.js +190 -0
  589. package/dist/esm/cli/commands/blueprint/router.d.ts +117 -0
  590. package/dist/esm/cli/commands/blueprint/router.js +480 -0
  591. package/dist/esm/cli/commands/blueprint/template-resolver.d.ts +19 -0
  592. package/dist/esm/cli/commands/blueprint/template-resolver.js +55 -0
  593. package/dist/esm/cli/commands/ci.d.ts +31 -0
  594. package/dist/esm/cli/commands/ci.js +76 -0
  595. package/dist/esm/cli/commands/compile.d.ts +21 -0
  596. package/dist/esm/cli/commands/compile.js +329 -0
  597. package/dist/esm/cli/commands/config.d.ts +55 -0
  598. package/dist/esm/cli/commands/config.js +272 -0
  599. package/dist/esm/cli/commands/dev.d.ts +17 -0
  600. package/dist/esm/cli/commands/dev.js +56 -0
  601. package/dist/esm/cli/commands/docs-core.d.ts +26 -0
  602. package/dist/esm/cli/commands/docs-core.js +88 -0
  603. package/dist/esm/cli/commands/docs.d.ts +9 -0
  604. package/dist/esm/cli/commands/docs.js +46 -0
  605. package/dist/esm/cli/commands/doctor.d.ts +10 -0
  606. package/dist/esm/cli/commands/doctor.js +53 -0
  607. package/dist/esm/cli/commands/e2e.d.ts +22 -0
  608. package/dist/esm/cli/commands/e2e.js +99 -0
  609. package/dist/esm/cli/commands/err.d.ts +11 -0
  610. package/dist/esm/cli/commands/err.js +73 -0
  611. package/dist/esm/cli/commands/format.d.ts +4 -0
  612. package/dist/esm/cli/commands/format.js +48 -0
  613. package/dist/esm/cli/commands/gain/index.d.ts +10 -0
  614. package/dist/esm/cli/commands/gain/index.js +83 -0
  615. package/dist/esm/cli/commands/hooks.d.ts +3 -0
  616. package/dist/esm/cli/commands/hooks.js +21 -0
  617. package/dist/esm/cli/commands/init/config.d.ts +36 -0
  618. package/dist/esm/cli/commands/init/config.js +116 -0
  619. package/dist/esm/cli/commands/init/detect-consumer.d.ts +49 -0
  620. package/dist/esm/cli/commands/init/detect-consumer.js +279 -0
  621. package/dist/esm/cli/commands/init/gitignore-patcher.d.ts +9 -0
  622. package/dist/esm/cli/commands/init/gitignore-patcher.js +133 -0
  623. package/dist/esm/cli/commands/init/host-visibility.d.ts +37 -0
  624. package/dist/esm/cli/commands/init/host-visibility.js +105 -0
  625. package/dist/esm/cli/commands/init/index.d.ts +23 -0
  626. package/dist/esm/cli/commands/init/index.js +751 -0
  627. package/dist/esm/cli/commands/init/merge.d.ts +33 -0
  628. package/dist/esm/cli/commands/init/merge.js +111 -0
  629. package/dist/esm/cli/commands/init/preflight.d.ts +15 -0
  630. package/dist/esm/cli/commands/init/preflight.js +87 -0
  631. package/dist/esm/cli/commands/init/prompts.d.ts +24 -0
  632. package/dist/esm/cli/commands/init/prompts.js +126 -0
  633. package/dist/esm/cli/commands/init/scaffold-agent-rules.d.ts +11 -0
  634. package/dist/esm/cli/commands/init/scaffold-agent-rules.js +58 -0
  635. package/dist/esm/cli/commands/init/scaffold-agent-skills.d.ts +11 -0
  636. package/dist/esm/cli/commands/init/scaffold-agent-skills.js +58 -0
  637. package/dist/esm/cli/commands/init/scaffold-agent.d.ts +15 -0
  638. package/dist/esm/cli/commands/init/scaffold-agent.js +63 -0
  639. package/dist/esm/cli/commands/init/scaffold-agents-md.d.ts +16 -0
  640. package/dist/esm/cli/commands/init/scaffold-agents-md.js +182 -0
  641. package/dist/esm/cli/commands/init/scaffold-base-kit.d.ts +9 -0
  642. package/dist/esm/cli/commands/init/scaffold-base-kit.js +183 -0
  643. package/dist/esm/cli/commands/init/scaffold-blueprints.d.ts +8 -0
  644. package/dist/esm/cli/commands/init/scaffold-blueprints.js +84 -0
  645. package/dist/esm/cli/commands/init/scaffold-catalog-ignore.d.ts +14 -0
  646. package/dist/esm/cli/commands/init/scaffold-catalog-ignore.js +48 -0
  647. package/dist/esm/cli/commands/init/scaffold-docs.d.ts +8 -0
  648. package/dist/esm/cli/commands/init/scaffold-docs.js +15 -0
  649. package/dist/esm/cli/commands/init/scaffold-monorepo-nav.d.ts +19 -0
  650. package/dist/esm/cli/commands/init/scaffold-monorepo-nav.js +101 -0
  651. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-global-normalize.d.ts +20 -0
  652. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-global-normalize.js +258 -0
  653. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-global-ownership.d.ts +3 -0
  654. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-global-ownership.js +36 -0
  655. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-ownership.d.ts +11 -0
  656. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-ownership.js +62 -0
  657. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-trust-sync.d.ts +24 -0
  658. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/codex-trust-sync.js +101 -0
  659. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.d.ts +68 -0
  660. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/index.js +585 -0
  661. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/skill-hooks.d.ts +21 -0
  662. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/skill-hooks.js +123 -0
  663. package/dist/esm/cli/commands/init/scaffolders/audit-hooks/index.d.ts +16 -0
  664. package/dist/esm/cli/commands/init/scaffolders/audit-hooks/index.js +65 -0
  665. package/dist/esm/cli/commands/init/scaffolders/claude-plugin/index.d.ts +33 -0
  666. package/dist/esm/cli/commands/init/scaffolders/claude-plugin/index.js +67 -0
  667. package/dist/esm/cli/commands/init/scaffolders/claude-rules/index.d.ts +7 -0
  668. package/dist/esm/cli/commands/init/scaffolders/claude-rules/index.js +127 -0
  669. package/dist/esm/cli/commands/init/scaffolders/codex-cli/index.d.ts +17 -0
  670. package/dist/esm/cli/commands/init/scaffolders/codex-cli/index.js +27 -0
  671. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.d.ts +79 -0
  672. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +189 -0
  673. package/dist/esm/cli/commands/init/scaffolders/context-mode/index.d.ts +24 -0
  674. package/dist/esm/cli/commands/init/scaffolders/context-mode/index.js +165 -0
  675. package/dist/esm/cli/commands/init/scaffolders/example-skill/index.d.ts +15 -0
  676. package/dist/esm/cli/commands/init/scaffolders/example-skill/index.js +31 -0
  677. package/dist/esm/cli/commands/init/scaffolders/gstack/index.d.ts +92 -0
  678. package/dist/esm/cli/commands/init/scaffolders/gstack/index.js +228 -0
  679. package/dist/esm/cli/commands/init/scaffolders/lore-commits/index.d.ts +12 -0
  680. package/dist/esm/cli/commands/init/scaffolders/lore-commits/index.js +24 -0
  681. package/dist/esm/cli/commands/init/scaffolders/omc/index.d.ts +41 -0
  682. package/dist/esm/cli/commands/init/scaffolders/omc/index.js +54 -0
  683. package/dist/esm/cli/commands/init/scaffolders/omx/index.d.ts +63 -0
  684. package/dist/esm/cli/commands/init/scaffolders/omx/index.js +251 -0
  685. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.d.ts +9 -0
  686. package/dist/esm/cli/commands/init/scaffolders/opencode-plugin/index.js +86 -0
  687. package/dist/esm/cli/commands/init/scaffolders/rtk/index.d.ts +25 -0
  688. package/dist/esm/cli/commands/init/scaffolders/rtk/index.js +55 -0
  689. package/dist/esm/cli/commands/init/scaffolders/runtime-check/index.d.ts +15 -0
  690. package/dist/esm/cli/commands/init/scaffolders/runtime-check/index.js +37 -0
  691. package/dist/esm/cli/commands/init/scaffolders/spinner.d.ts +23 -0
  692. package/dist/esm/cli/commands/init/scaffolders/spinner.js +32 -0
  693. package/dist/esm/cli/commands/init/scaffolders/subagents/index.d.ts +7 -0
  694. package/dist/esm/cli/commands/init/scaffolders/subagents/index.js +88 -0
  695. package/dist/esm/cli/commands/init/scaffolders/version-pin.d.ts +19 -0
  696. package/dist/esm/cli/commands/init/scaffolders/version-pin.js +95 -0
  697. package/dist/esm/cli/commands/init/scaffolders/vision/index.d.ts +10 -0
  698. package/dist/esm/cli/commands/init/scaffolders/vision/index.js +67 -0
  699. package/dist/esm/cli/commands/init/scaffolders/vision/interview.d.ts +22 -0
  700. package/dist/esm/cli/commands/init/scaffolders/vision/interview.js +73 -0
  701. package/dist/esm/cli/commands/init/scaffolders/workspace-config/index.d.ts +28 -0
  702. package/dist/esm/cli/commands/init/scaffolders/workspace-config/index.js +40 -0
  703. package/dist/esm/cli/commands/lint.d.ts +4 -0
  704. package/dist/esm/cli/commands/lint.js +40 -0
  705. package/dist/esm/cli/commands/mcp.d.ts +4 -0
  706. package/dist/esm/cli/commands/mcp.js +18 -0
  707. package/dist/esm/cli/commands/roadmap.d.ts +7 -0
  708. package/dist/esm/cli/commands/roadmap.js +79 -0
  709. package/dist/esm/cli/commands/rule.d.ts +8 -0
  710. package/dist/esm/cli/commands/rule.js +59 -0
  711. package/dist/esm/cli/commands/skill.d.ts +20 -0
  712. package/dist/esm/cli/commands/skill.js +160 -0
  713. package/dist/esm/cli/commands/sync.d.ts +14 -0
  714. package/dist/esm/cli/commands/sync.js +132 -0
  715. package/dist/esm/cli/commands/tech-debt/index.d.ts +5 -0
  716. package/dist/esm/cli/commands/tech-debt/index.js +5 -0
  717. package/dist/esm/cli/commands/tech-debt/router-dispatch.d.ts +22 -0
  718. package/dist/esm/cli/commands/tech-debt/router-dispatch.js +436 -0
  719. package/dist/esm/cli/commands/tech-debt/router.d.ts +10 -0
  720. package/dist/esm/cli/commands/tech-debt/router.js +30 -0
  721. package/dist/esm/cli/commands/test.d.ts +12 -0
  722. package/dist/esm/cli/commands/test.js +88 -0
  723. package/dist/esm/cli/commands/typecheck.d.ts +18 -0
  724. package/dist/esm/cli/commands/typecheck.js +57 -0
  725. package/dist/esm/cli/commands/worktree/router-dispatch.d.ts +39 -0
  726. package/dist/esm/cli/commands/worktree/router-dispatch.js +217 -0
  727. package/dist/esm/cli/commands/worktree/router.d.ts +10 -0
  728. package/dist/esm/cli/commands/worktree/router.js +34 -0
  729. package/dist/esm/cli/utils.d.ts +45 -0
  730. package/dist/esm/cli/utils.js +156 -0
  731. package/dist/esm/codex/app-server/client.d.ts +50 -0
  732. package/dist/esm/codex/app-server/client.js +202 -0
  733. package/dist/esm/codex/app-server/types.d.ts +240 -0
  734. package/dist/esm/codex/app-server/types.js +103 -0
  735. package/dist/esm/compiler/flatten.d.ts +10 -0
  736. package/dist/esm/compiler/flatten.js +71 -0
  737. package/dist/esm/compiler/manifests/_versions.d.ts +7 -0
  738. package/dist/esm/compiler/manifests/_versions.js +7 -0
  739. package/dist/esm/compiler/manifests/claude.d.ts +9 -0
  740. package/dist/esm/compiler/manifests/claude.js +36 -0
  741. package/dist/esm/compiler/manifests/codex.d.ts +9 -0
  742. package/dist/esm/compiler/manifests/codex.js +23 -0
  743. package/dist/esm/compiler/manifests/cursor.d.ts +9 -0
  744. package/dist/esm/compiler/manifests/cursor.js +28 -0
  745. package/dist/esm/compiler/manifests/gemini.d.ts +9 -0
  746. package/dist/esm/compiler/manifests/gemini.js +20 -0
  747. package/dist/esm/compiler/memory/directives.d.ts +23 -0
  748. package/dist/esm/compiler/memory/directives.js +108 -0
  749. package/dist/esm/compiler/memory/directives.schema.d.ts +55 -0
  750. package/dist/esm/compiler/memory/directives.schema.js +32 -0
  751. package/dist/esm/compiler/memory/merger.d.ts +17 -0
  752. package/dist/esm/compiler/memory/merger.js +122 -0
  753. package/dist/esm/compiler/memory/precedence.d.ts +15 -0
  754. package/dist/esm/compiler/memory/precedence.js +40 -0
  755. package/dist/esm/compiler/memory/provenance.d.ts +13 -0
  756. package/dist/esm/compiler/memory/provenance.js +8 -0
  757. package/dist/esm/compiler/orphans.d.ts +8 -0
  758. package/dist/esm/compiler/orphans.js +58 -0
  759. package/dist/esm/compiler/schema.d.ts +47 -0
  760. package/dist/esm/compiler/schema.js +49 -0
  761. package/dist/esm/config/docs-lint/cli/check-internal-links.d.ts +13 -0
  762. package/dist/esm/config/docs-lint/cli/check-internal-links.js +161 -0
  763. package/dist/esm/config/docs-lint/cli/check-refs.d.ts +9 -0
  764. package/dist/esm/config/docs-lint/cli/check-refs.js +165 -0
  765. package/dist/esm/config/docs-lint/cli/check-stale.d.ts +9 -0
  766. package/dist/esm/config/docs-lint/cli/check-stale.js +116 -0
  767. package/dist/esm/config/docs-lint/cli/commands/migrate-command.d.ts +22 -0
  768. package/dist/esm/config/docs-lint/cli/commands/migrate-command.js +254 -0
  769. package/dist/esm/config/docs-lint/cli/commands/validate-command.d.ts +28 -0
  770. package/dist/esm/config/docs-lint/cli/commands/validate-command.js +363 -0
  771. package/dist/esm/config/docs-lint/cli/factories.d.ts +54 -0
  772. package/dist/esm/config/docs-lint/cli/factories.js +85 -0
  773. package/dist/esm/config/docs-lint/cli/fixers/code-language.d.ts +34 -0
  774. package/dist/esm/config/docs-lint/cli/fixers/code-language.js +277 -0
  775. package/dist/esm/config/docs-lint/cli/interfaces.d.ts +55 -0
  776. package/dist/esm/config/docs-lint/cli/interfaces.js +6 -0
  777. package/dist/esm/config/docs-lint/cli/migrate.d.ts +3 -0
  778. package/dist/esm/config/docs-lint/cli/migrate.js +53 -0
  779. package/dist/esm/config/docs-lint/cli/planning-path.d.ts +2 -0
  780. package/dist/esm/config/docs-lint/cli/planning-path.js +29 -0
  781. package/dist/esm/config/docs-lint/cli/validate.d.ts +3 -0
  782. package/dist/esm/config/docs-lint/cli/validate.js +47 -0
  783. package/dist/esm/config/docs-lint/cli/validators/code-density.d.ts +7 -0
  784. package/dist/esm/config/docs-lint/cli/validators/code-density.js +15 -0
  785. package/dist/esm/config/docs-lint/cli/validators/command-safety.d.ts +19 -0
  786. package/dist/esm/config/docs-lint/cli/validators/command-safety.js +195 -0
  787. package/dist/esm/config/docs-lint/cli/validators/context-limits.d.ts +58 -0
  788. package/dist/esm/config/docs-lint/cli/validators/context-limits.js +212 -0
  789. package/dist/esm/config/docs-lint/cli/validators/deprecated-commands.d.ts +9 -0
  790. package/dist/esm/config/docs-lint/cli/validators/deprecated-commands.js +112 -0
  791. package/dist/esm/config/docs-lint/cli/validators/filename.d.ts +12 -0
  792. package/dist/esm/config/docs-lint/cli/validators/filename.js +128 -0
  793. package/dist/esm/config/docs-lint/cli/validators/imports.d.ts +30 -0
  794. package/dist/esm/config/docs-lint/cli/validators/imports.js +163 -0
  795. package/dist/esm/config/docs-lint/cli/validators/index.d.ts +8 -0
  796. package/dist/esm/config/docs-lint/cli/validators/index.js +8 -0
  797. package/dist/esm/config/docs-lint/cli/validators/links.d.ts +30 -0
  798. package/dist/esm/config/docs-lint/cli/validators/links.js +134 -0
  799. package/dist/esm/config/docs-lint/cli/validators/markdownlint.d.ts +11 -0
  800. package/dist/esm/config/docs-lint/cli/validators/markdownlint.js +17 -0
  801. package/dist/esm/config/docs-lint/cli/validators/structure.d.ts +10 -0
  802. package/dist/esm/config/docs-lint/cli/validators/structure.js +75 -0
  803. package/dist/esm/config/docs-lint/generator/frontmatter-validator.d.ts +6 -0
  804. package/dist/esm/config/docs-lint/generator/frontmatter-validator.js +72 -0
  805. package/dist/esm/config/docs-lint/generator/index.d.ts +11 -0
  806. package/dist/esm/config/docs-lint/generator/index.js +10 -0
  807. package/dist/esm/config/docs-lint/generator/markdown-generator.d.ts +6 -0
  808. package/dist/esm/config/docs-lint/generator/markdown-generator.js +78 -0
  809. package/dist/esm/config/docs-lint/generator/template-loader.d.ts +18 -0
  810. package/dist/esm/config/docs-lint/generator/template-loader.js +66 -0
  811. package/dist/esm/config/docs-lint/generator/types.d.ts +100 -0
  812. package/dist/esm/config/docs-lint/generator/types.js +2 -0
  813. package/dist/esm/config/docs-lint/index.d.ts +34 -0
  814. package/dist/esm/config/docs-lint/index.js +3 -0
  815. package/dist/esm/config/docs-lint/parsers/bold-metadata.d.ts +28 -0
  816. package/dist/esm/config/docs-lint/parsers/bold-metadata.js +176 -0
  817. package/dist/esm/config/docs-lint/parsers/frontmatter.d.ts +20 -0
  818. package/dist/esm/config/docs-lint/parsers/frontmatter.js +67 -0
  819. package/dist/esm/config/docs-lint/parsers/index.d.ts +3 -0
  820. package/dist/esm/config/docs-lint/parsers/index.js +3 -0
  821. package/dist/esm/config/docs-lint/schemas/adaptation.d.ts +28 -0
  822. package/dist/esm/config/docs-lint/schemas/adaptation.js +18 -0
  823. package/dist/esm/config/docs-lint/schemas/agents.d.ts +76 -0
  824. package/dist/esm/config/docs-lint/schemas/agents.js +29 -0
  825. package/dist/esm/config/docs-lint/schemas/audit.d.ts +52 -0
  826. package/dist/esm/config/docs-lint/schemas/audit.js +20 -0
  827. package/dist/esm/config/docs-lint/schemas/common.d.ts +68 -0
  828. package/dist/esm/config/docs-lint/schemas/common.js +73 -0
  829. package/dist/esm/config/docs-lint/schemas/cookbook.d.ts +48 -0
  830. package/dist/esm/config/docs-lint/schemas/cookbook.js +21 -0
  831. package/dist/esm/config/docs-lint/schemas/core.d.ts +189 -0
  832. package/dist/esm/config/docs-lint/schemas/core.js +54 -0
  833. package/dist/esm/config/docs-lint/schemas/decision.d.ts +18 -0
  834. package/dist/esm/config/docs-lint/schemas/decision.js +9 -0
  835. package/dist/esm/config/docs-lint/schemas/draft.d.ts +36 -0
  836. package/dist/esm/config/docs-lint/schemas/draft.js +35 -0
  837. package/dist/esm/config/docs-lint/schemas/evaluation.d.ts +43 -0
  838. package/dist/esm/config/docs-lint/schemas/evaluation.js +22 -0
  839. package/dist/esm/config/docs-lint/schemas/implementation-plan.d.ts +62 -0
  840. package/dist/esm/config/docs-lint/schemas/implementation-plan.js +34 -0
  841. package/dist/esm/config/docs-lint/schemas/index.d.ts +51 -0
  842. package/dist/esm/config/docs-lint/schemas/index.js +109 -0
  843. package/dist/esm/config/docs-lint/schemas/ongoing-initiative.d.ts +99 -0
  844. package/dist/esm/config/docs-lint/schemas/ongoing-initiative.js +31 -0
  845. package/dist/esm/config/docs-lint/schemas/parent-roadmap.d.ts +39 -0
  846. package/dist/esm/config/docs-lint/schemas/parent-roadmap.js +24 -0
  847. package/dist/esm/config/docs-lint/schemas/research.d.ts +26 -0
  848. package/dist/esm/config/docs-lint/schemas/research.js +20 -0
  849. package/dist/esm/config/docs-lint/schemas/rule.d.ts +48 -0
  850. package/dist/esm/config/docs-lint/schemas/rule.js +12 -0
  851. package/dist/esm/config/e2e-preset/index.d.ts +17 -0
  852. package/dist/esm/config/e2e-preset/index.js +29 -0
  853. package/dist/esm/config/e2e-preset/playwright.d.ts +17 -0
  854. package/dist/esm/config/e2e-preset/playwright.js +12 -0
  855. package/dist/esm/config/launch/contracts.d.ts +100 -0
  856. package/dist/esm/config/launch/contracts.js +13 -0
  857. package/dist/esm/config/launch/dev-contracts.d.ts +47 -0
  858. package/dist/esm/config/launch/dev-contracts.js +8 -0
  859. package/dist/esm/config/launch/dev-manifest.d.ts +42 -0
  860. package/dist/esm/config/launch/dev-manifest.js +196 -0
  861. package/dist/esm/config/launch/index.d.ts +14 -0
  862. package/dist/esm/config/launch/index.js +12 -0
  863. package/dist/esm/config/launch/launch-profile.d.ts +47 -0
  864. package/dist/esm/config/launch/launch-profile.js +39 -0
  865. package/dist/esm/config/launch/provision-stack.d.ts +64 -0
  866. package/dist/esm/config/launch/provision-stack.js +45 -0
  867. package/dist/esm/config/oxlint/code-safety.d.ts +19 -0
  868. package/dist/esm/config/oxlint/code-safety.js +90 -0
  869. package/dist/esm/config/oxlint/foundation-purity.d.ts +22 -0
  870. package/dist/esm/config/oxlint/foundation-purity.js +53 -0
  871. package/dist/esm/config/oxlint/graphql-conventions.d.ts +24 -0
  872. package/dist/esm/config/oxlint/graphql-conventions.js +204 -0
  873. package/dist/esm/config/oxlint/import-hygiene.d.ts +35 -0
  874. package/dist/esm/config/oxlint/import-hygiene.js +208 -0
  875. package/dist/esm/config/oxlint/index.d.ts +23 -0
  876. package/dist/esm/config/oxlint/index.js +29 -0
  877. package/dist/esm/config/oxlint/monorepo-paths.d.ts +19 -0
  878. package/dist/esm/config/oxlint/monorepo-paths.js +129 -0
  879. package/dist/esm/config/oxlint/oxlint-config.fixture.d.ts +3 -0
  880. package/dist/esm/config/oxlint/oxlint-config.fixture.js +5 -0
  881. package/dist/esm/config/oxlint/query-patterns.d.ts +25 -0
  882. package/dist/esm/config/oxlint/query-patterns.js +126 -0
  883. package/dist/esm/config/oxlint/testing-quality.d.ts +36 -0
  884. package/dist/esm/config/oxlint/testing-quality.js +187 -0
  885. package/dist/esm/config/oxlint/tier-boundaries.d.ts +36 -0
  886. package/dist/esm/config/oxlint/tier-boundaries.js +134 -0
  887. package/dist/esm/config/stryker/index.d.ts +44 -0
  888. package/dist/esm/config/stryker/index.js +79 -0
  889. package/dist/esm/config/test-preset/index.d.ts +2 -0
  890. package/dist/esm/config/test-preset/index.js +2 -0
  891. package/dist/esm/config/test-preset/vitest.d.ts +26 -0
  892. package/dist/esm/config/test-preset/vitest.js +31 -0
  893. package/dist/esm/config/tsconfig/base.json +37 -0
  894. package/dist/esm/config/tsconfig/cloudflare.json +10 -0
  895. package/dist/esm/config/tsconfig/library.json +16 -0
  896. package/dist/esm/config/tsconfig/react-library.json +9 -0
  897. package/dist/esm/config/tsconfig/react-router.json +10 -0
  898. package/dist/esm/config/vitest/bun-sqlite-shim.d.ts +14 -0
  899. package/dist/esm/config/vitest/bun-sqlite-shim.js +14 -0
  900. package/dist/esm/config/vitest/consumer-package.d.ts +4 -0
  901. package/dist/esm/config/vitest/consumer-package.js +63 -0
  902. package/dist/esm/config/vitest/flakiness-reporter.d.ts +7 -0
  903. package/dist/esm/config/vitest/flakiness-reporter.js +53 -0
  904. package/dist/esm/config/vitest/generated-runtime-aliases.d.ts +6 -0
  905. package/dist/esm/config/vitest/generated-runtime-aliases.js +3 -0
  906. package/dist/esm/config/vitest/node-setup.d.ts +6 -0
  907. package/dist/esm/config/vitest/node-setup.js +16 -0
  908. package/dist/esm/config/vitest/node.d.ts +43 -0
  909. package/dist/esm/config/vitest/node.js +180 -0
  910. package/dist/esm/config/vitest/pool-defaults.d.ts +11 -0
  911. package/dist/esm/config/vitest/pool-defaults.js +43 -0
  912. package/dist/esm/config/vitest/react-router.d.ts +22 -0
  913. package/dist/esm/config/vitest/react-router.js +83 -0
  914. package/dist/esm/config/vitest/react-setup.d.ts +13 -0
  915. package/dist/esm/config/vitest/react-setup.js +27 -0
  916. package/dist/esm/config/vitest/react.d.ts +22 -0
  917. package/dist/esm/config/vitest/react.js +85 -0
  918. package/dist/esm/config/vitest/version-guard.d.ts +7 -0
  919. package/dist/esm/config/vitest/version-guard.js +42 -0
  920. package/dist/esm/config/vitest/workers.d.ts +28 -0
  921. package/dist/esm/config/vitest/workers.js +44 -0
  922. package/dist/esm/config/workers-test/cloudflare-types.d.ts +30 -0
  923. package/dist/esm/config/workers-test/cloudflare-types.js +2 -0
  924. package/dist/esm/config/workers-test/durable-objects.d.ts +60 -0
  925. package/dist/esm/config/workers-test/durable-objects.js +73 -0
  926. package/dist/esm/config/workers-test/env.d.ts +58 -0
  927. package/dist/esm/config/workers-test/env.js +74 -0
  928. package/dist/esm/config/workers-test/execution-context.d.ts +21 -0
  929. package/dist/esm/config/workers-test/execution-context.js +22 -0
  930. package/dist/esm/config/workers-test/index.d.ts +16 -0
  931. package/dist/esm/config/workers-test/index.js +15 -0
  932. package/dist/esm/config/workers-test/requests.d.ts +44 -0
  933. package/dist/esm/config/workers-test/requests.js +71 -0
  934. package/dist/esm/config/workers-test/setup.d.ts +63 -0
  935. package/dist/esm/config/workers-test/setup.js +86 -0
  936. package/dist/esm/content/audit.d.ts +20 -0
  937. package/dist/esm/content/audit.js +164 -0
  938. package/dist/esm/content/dispatch.d.ts +32 -0
  939. package/dist/esm/content/dispatch.js +204 -0
  940. package/dist/esm/content/loader.d.ts +50 -0
  941. package/dist/esm/content/loader.js +166 -0
  942. package/dist/esm/content/schema.d.ts +123 -0
  943. package/dist/esm/content/schema.js +125 -0
  944. package/dist/esm/dev/dev-link-state.d.ts +22 -0
  945. package/dist/esm/dev/dev-link-state.js +51 -0
  946. package/dist/esm/dev/index.d.ts +2 -0
  947. package/dist/esm/dev/index.js +2 -0
  948. package/dist/esm/dev/load-manifest.d.ts +35 -0
  949. package/dist/esm/dev/load-manifest.js +182 -0
  950. package/dist/esm/dev/restore-dev-links/index.d.ts +30 -0
  951. package/dist/esm/dev/restore-dev-links/index.js +103 -0
  952. package/dist/esm/docs-linter/blueprint-plan.d.ts +80 -0
  953. package/dist/esm/docs-linter/blueprint-plan.js +427 -0
  954. package/dist/esm/docs-linter/index.d.ts +8 -0
  955. package/dist/esm/docs-linter/index.js +7 -0
  956. package/dist/esm/docs-linter/types.d.ts +16 -0
  957. package/dist/esm/docs-linter/types.js +8 -0
  958. package/dist/esm/e2e/command-builder.d.ts +3 -0
  959. package/dist/esm/e2e/command-builder.js +98 -0
  960. package/dist/esm/e2e/command-host-adapter.d.ts +30 -0
  961. package/dist/esm/e2e/command-host-adapter.js +70 -0
  962. package/dist/esm/e2e/config.d.ts +26 -0
  963. package/dist/esm/e2e/config.js +39 -0
  964. package/dist/esm/e2e/execution.d.ts +14 -0
  965. package/dist/esm/e2e/execution.js +148 -0
  966. package/dist/esm/e2e/host-adapter.d.ts +6 -0
  967. package/dist/esm/e2e/host-adapter.js +22 -0
  968. package/dist/esm/e2e/index.d.ts +9 -0
  969. package/dist/esm/e2e/index.js +8 -0
  970. package/dist/esm/e2e/load-host-adapter.d.ts +43 -0
  971. package/dist/esm/e2e/load-host-adapter.js +150 -0
  972. package/dist/esm/e2e/run-planner.d.ts +11 -0
  973. package/dist/esm/e2e/run-planner.js +186 -0
  974. package/dist/esm/e2e/suite-registry.d.ts +9 -0
  975. package/dist/esm/e2e/suite-registry.js +30 -0
  976. package/dist/esm/e2e/types.d.ts +81 -0
  977. package/dist/esm/e2e/types.js +2 -0
  978. package/dist/esm/format/errors.d.ts +2 -0
  979. package/dist/esm/format/errors.js +15 -0
  980. package/dist/esm/format/format.d.ts +2 -0
  981. package/dist/esm/format/format.js +16 -0
  982. package/dist/esm/format/index.d.ts +35 -0
  983. package/dist/esm/format/index.js +67 -0
  984. package/dist/esm/hooks/check-dev-link/index.d.ts +19 -0
  985. package/dist/esm/hooks/check-dev-link/index.js +87 -0
  986. package/dist/esm/hooks/doctor.d.ts +34 -0
  987. package/dist/esm/hooks/doctor.js +699 -0
  988. package/dist/esm/hooks/guard-switch/index.d.ts +3 -0
  989. package/dist/esm/hooks/guard-switch/index.js +18 -0
  990. package/dist/esm/hooks/guard-switch/state.d.ts +4 -0
  991. package/dist/esm/hooks/guard-switch/state.js +30 -0
  992. package/dist/esm/hooks/post-tool/lint-after-edit.d.ts +17 -0
  993. package/dist/esm/hooks/post-tool/lint-after-edit.js +57 -0
  994. package/dist/esm/hooks/pretool-guard/dev-routing.d.ts +21 -0
  995. package/dist/esm/hooks/pretool-guard/dev-routing.js +658 -0
  996. package/dist/esm/hooks/pretool-guard/index.d.ts +5 -0
  997. package/dist/esm/hooks/pretool-guard/index.js +11 -0
  998. package/dist/esm/hooks/pretool-guard/logger.d.ts +32 -0
  999. package/dist/esm/hooks/pretool-guard/logger.js +82 -0
  1000. package/dist/esm/hooks/pretool-guard/runner.d.ts +16 -0
  1001. package/dist/esm/hooks/pretool-guard/runner.js +149 -0
  1002. package/dist/esm/hooks/pretool-guard/validators/blueprint.d.ts +3 -0
  1003. package/dist/esm/hooks/pretool-guard/validators/blueprint.js +16 -0
  1004. package/dist/esm/hooks/pretool-guard/validators/command-file.d.ts +3 -0
  1005. package/dist/esm/hooks/pretool-guard/validators/command-file.js +36 -0
  1006. package/dist/esm/hooks/pretool-guard/validators/complexity.d.ts +3 -0
  1007. package/dist/esm/hooks/pretool-guard/validators/complexity.js +24 -0
  1008. package/dist/esm/hooks/pretool-guard/validators/dangerous-commands.d.ts +4 -0
  1009. package/dist/esm/hooks/pretool-guard/validators/dangerous-commands.js +60 -0
  1010. package/dist/esm/hooks/pretool-guard/validators/docs-governance.d.ts +2 -0
  1011. package/dist/esm/hooks/pretool-guard/validators/docs-governance.js +2 -0
  1012. package/dist/esm/hooks/pretool-guard/validators/file-conventions.d.ts +3 -0
  1013. package/dist/esm/hooks/pretool-guard/validators/file-conventions.js +67 -0
  1014. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.d.ts +66 -0
  1015. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +439 -0
  1016. package/dist/esm/hooks/pretool-guard/validators/index.d.ts +14 -0
  1017. package/dist/esm/hooks/pretool-guard/validators/index.js +26 -0
  1018. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +16 -0
  1019. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +50 -0
  1020. package/dist/esm/hooks/pretool-guard/validators/package-imports.d.ts +10 -0
  1021. package/dist/esm/hooks/pretool-guard/validators/package-imports.js +36 -0
  1022. package/dist/esm/hooks/pretool-guard/validators/package-imports.types.d.ts +8 -0
  1023. package/dist/esm/hooks/pretool-guard/validators/package-imports.types.js +2 -0
  1024. package/dist/esm/hooks/pretool-guard/validators/path-contract.d.ts +15 -0
  1025. package/dist/esm/hooks/pretool-guard/validators/path-contract.js +105 -0
  1026. package/dist/esm/hooks/pretool-guard/validators/plan-frontmatter.d.ts +13 -0
  1027. package/dist/esm/hooks/pretool-guard/validators/plan-frontmatter.js +121 -0
  1028. package/dist/esm/hooks/pretool-guard/validators/skip-result.d.ts +3 -0
  1029. package/dist/esm/hooks/pretool-guard/validators/skip-result.js +4 -0
  1030. package/dist/esm/hooks/pretool-guard/validators/test-quality.d.ts +22 -0
  1031. package/dist/esm/hooks/pretool-guard/validators/test-quality.js +218 -0
  1032. package/dist/esm/hooks/pretool-guard/validators/ux-quality.d.ts +3 -0
  1033. package/dist/esm/hooks/pretool-guard/validators/ux-quality.js +80 -0
  1034. package/dist/esm/hooks/sessionstart/index.d.ts +16 -0
  1035. package/dist/esm/hooks/sessionstart/index.js +122 -0
  1036. package/dist/esm/hooks/sessionstart/update-banner.d.ts +2 -0
  1037. package/dist/esm/hooks/sessionstart/update-banner.js +66 -0
  1038. package/dist/esm/hooks/shared/hook-bootstrap.d.ts +28 -0
  1039. package/dist/esm/hooks/shared/hook-bootstrap.js +62 -0
  1040. package/dist/esm/hooks/shared/mcp-sentinel.d.ts +10 -0
  1041. package/dist/esm/hooks/shared/mcp-sentinel.js +106 -0
  1042. package/dist/esm/hooks/shared/routing-block.d.ts +8 -0
  1043. package/dist/esm/hooks/shared/routing-block.js +140 -0
  1044. package/dist/esm/hooks/shared/types.d.ts +24 -0
  1045. package/dist/esm/hooks/shared/types.js +48 -0
  1046. package/dist/esm/hooks/shared/validators/blueprint.d.ts +17 -0
  1047. package/dist/esm/hooks/shared/validators/blueprint.js +98 -0
  1048. package/dist/esm/hooks/shared/validators/docs-governance.d.ts +3 -0
  1049. package/dist/esm/hooks/shared/validators/docs-governance.js +30 -0
  1050. package/dist/esm/hooks/shared/worktree-root.d.ts +2 -0
  1051. package/dist/esm/hooks/shared/worktree-root.js +46 -0
  1052. package/dist/esm/hooks/stop/qa-changed-files.d.ts +14 -0
  1053. package/dist/esm/hooks/stop/qa-changed-files.js +96 -0
  1054. package/dist/esm/hooks/test-quality-check.d.ts +5 -0
  1055. package/dist/esm/hooks/test-quality-check.js +61 -0
  1056. package/dist/esm/index.d.ts +13 -0
  1057. package/dist/esm/index.js +11 -0
  1058. package/dist/esm/lint/index.d.ts +53 -0
  1059. package/dist/esm/lint/index.js +115 -0
  1060. package/dist/esm/local.d.ts +19 -0
  1061. package/dist/esm/local.js +14 -0
  1062. package/dist/esm/mcp/_tail-hints.d.ts +31 -0
  1063. package/dist/esm/mcp/_tail-hints.js +86 -0
  1064. package/dist/esm/mcp/auto-discover.d.ts +65 -0
  1065. package/dist/esm/mcp/auto-discover.js +108 -0
  1066. package/dist/esm/mcp/blueprint-server.d.ts +137 -0
  1067. package/dist/esm/mcp/blueprint-server.js +2131 -0
  1068. package/dist/esm/mcp/blueprint-server.platform-first.test-harness.d.ts +31 -0
  1069. package/dist/esm/mcp/blueprint-server.platform-first.test-harness.js +216 -0
  1070. package/dist/esm/mcp/blueprint-server.test-harness.d.ts +49 -0
  1071. package/dist/esm/mcp/blueprint-server.test-harness.js +195 -0
  1072. package/dist/esm/mcp/cli.d.ts +10 -0
  1073. package/dist/esm/mcp/cli.js +48 -0
  1074. package/dist/esm/mcp/runners/test.d.ts +36 -0
  1075. package/dist/esm/mcp/runners/test.js +330 -0
  1076. package/dist/esm/mcp/server.d.ts +24 -0
  1077. package/dist/esm/mcp/server.js +142 -0
  1078. package/dist/esm/mcp/tools/_shared/project-root.d.ts +29 -0
  1079. package/dist/esm/mcp/tools/_shared/project-root.js +61 -0
  1080. package/dist/esm/mcp/tools/_shared/redact.d.ts +2 -0
  1081. package/dist/esm/mcp/tools/_shared/redact.js +29 -0
  1082. package/dist/esm/mcp/tools/_shared/result.d.ts +79 -0
  1083. package/dist/esm/mcp/tools/_shared/result.js +85 -0
  1084. package/dist/esm/mcp/tools/_shared/run-command.d.ts +37 -0
  1085. package/dist/esm/mcp/tools/_shared/run-command.js +122 -0
  1086. package/dist/esm/mcp/tools/_shared/test-budget-contract.d.ts +18 -0
  1087. package/dist/esm/mcp/tools/_shared/test-budget-contract.js +24 -0
  1088. package/dist/esm/mcp/tools/_shared/ui-detection.d.ts +2 -0
  1089. package/dist/esm/mcp/tools/_shared/ui-detection.js +19 -0
  1090. package/dist/esm/mcp/tools/audit.d.ts +45 -0
  1091. package/dist/esm/mcp/tools/audit.js +345 -0
  1092. package/dist/esm/mcp/tools/ci-act.d.ts +4 -0
  1093. package/dist/esm/mcp/tools/ci-act.js +91 -0
  1094. package/dist/esm/mcp/tools/e2e.d.ts +31 -0
  1095. package/dist/esm/mcp/tools/e2e.js +116 -0
  1096. package/dist/esm/mcp/tools/format.d.ts +27 -0
  1097. package/dist/esm/mcp/tools/format.js +107 -0
  1098. package/dist/esm/mcp/tools/lint.d.ts +26 -0
  1099. package/dist/esm/mcp/tools/lint.js +229 -0
  1100. package/dist/esm/mcp/tools/qa.d.ts +39 -0
  1101. package/dist/esm/mcp/tools/qa.js +218 -0
  1102. package/dist/esm/mcp/tools/test.d.ts +25 -0
  1103. package/dist/esm/mcp/tools/test.js +112 -0
  1104. package/dist/esm/mcp/tools/typecheck.d.ts +27 -0
  1105. package/dist/esm/mcp/tools/typecheck.js +186 -0
  1106. package/dist/esm/mcp/tools/worker-tail.d.ts +4 -0
  1107. package/dist/esm/mcp/tools/worker-tail.js +121 -0
  1108. package/dist/esm/output-transforms/generic.d.ts +3 -0
  1109. package/dist/esm/output-transforms/generic.js +20 -0
  1110. package/dist/esm/output-transforms/index.d.ts +34 -0
  1111. package/dist/esm/output-transforms/index.js +41 -0
  1112. package/dist/esm/output-transforms/metadata.d.ts +8 -0
  1113. package/dist/esm/output-transforms/metadata.js +24 -0
  1114. package/dist/esm/output-transforms/oxlint.d.ts +3 -0
  1115. package/dist/esm/output-transforms/oxlint.js +85 -0
  1116. package/dist/esm/output-transforms/passthrough.d.ts +3 -0
  1117. package/dist/esm/output-transforms/passthrough.js +11 -0
  1118. package/dist/esm/output-transforms/rulesync.d.ts +3 -0
  1119. package/dist/esm/output-transforms/rulesync.js +80 -0
  1120. package/dist/esm/output-transforms/should-compact.d.ts +7 -0
  1121. package/dist/esm/output-transforms/should-compact.js +14 -0
  1122. package/dist/esm/output-transforms/tsc.d.ts +3 -0
  1123. package/dist/esm/output-transforms/tsc.js +45 -0
  1124. package/dist/esm/output-transforms/vitest.d.ts +3 -0
  1125. package/dist/esm/output-transforms/vitest.js +120 -0
  1126. package/dist/esm/package.json +92 -0
  1127. package/dist/esm/paths/state-root.d.ts +23 -0
  1128. package/dist/esm/paths/state-root.js +121 -0
  1129. package/dist/esm/quality-engine/command-builder.d.ts +141 -0
  1130. package/dist/esm/quality-engine/command-builder.js +285 -0
  1131. package/dist/esm/quality-engine/index.d.ts +15 -0
  1132. package/dist/esm/quality-engine/index.js +16 -0
  1133. package/dist/esm/quality-engine/log-paths.d.ts +44 -0
  1134. package/dist/esm/quality-engine/log-paths.js +73 -0
  1135. package/dist/esm/quality-engine/package-import-rules.d.ts +69 -0
  1136. package/dist/esm/quality-engine/package-import-rules.js +491 -0
  1137. package/dist/esm/quality-engine/target-resolver.d.ts +187 -0
  1138. package/dist/esm/quality-engine/target-resolver.js +552 -0
  1139. package/dist/esm/quality-engine/test-classification.d.ts +7 -0
  1140. package/dist/esm/quality-engine/test-classification.js +85 -0
  1141. package/dist/esm/quality-engine/workspace-config.d.ts +68 -0
  1142. package/dist/esm/quality-engine/workspace-config.js +131 -0
  1143. package/dist/esm/runners/claude-subagent/index.d.ts +11 -0
  1144. package/dist/esm/runners/claude-subagent/index.js +114 -0
  1145. package/dist/esm/runners/claude-subagent/types.d.ts +7 -0
  1146. package/dist/esm/runners/claude-subagent/types.js +5 -0
  1147. package/dist/esm/runners/codex-exec/index.d.ts +16 -0
  1148. package/dist/esm/runners/codex-exec/index.js +105 -0
  1149. package/dist/esm/runners/index.d.ts +3 -0
  1150. package/dist/esm/runners/index.js +2 -0
  1151. package/dist/esm/runners/local-worktree/index.d.ts +19 -0
  1152. package/dist/esm/runners/local-worktree/index.js +85 -0
  1153. package/dist/esm/runners/local-worktree/path.d.ts +10 -0
  1154. package/dist/esm/runners/local-worktree/path.js +14 -0
  1155. package/dist/esm/runners/select.d.ts +12 -0
  1156. package/dist/esm/runners/select.js +38 -0
  1157. package/dist/esm/runners/types.d.ts +70 -0
  1158. package/dist/esm/runners/types.js +62 -0
  1159. package/dist/esm/secret-gate/runner.d.ts +25 -0
  1160. package/dist/esm/secret-gate/runner.js +106 -0
  1161. package/dist/esm/session-memory/fetch-index.d.ts +13 -0
  1162. package/dist/esm/session-memory/fetch-index.js +80 -0
  1163. package/dist/esm/session-memory/repo-hash.d.ts +3 -0
  1164. package/dist/esm/session-memory/repo-hash.js +20 -0
  1165. package/dist/esm/session-memory/session.d.ts +10 -0
  1166. package/dist/esm/session-memory/session.js +105 -0
  1167. package/dist/esm/session-memory/store.d.ts +17 -0
  1168. package/dist/esm/session-memory/store.js +168 -0
  1169. package/dist/esm/session-memory/types.d.ts +58 -0
  1170. package/dist/esm/session-memory/types.js +2 -0
  1171. package/dist/esm/symlinker/consumers.d.ts +97 -0
  1172. package/dist/esm/symlinker/consumers.js +87 -0
  1173. package/dist/esm/symlinker/frontmatter.d.ts +15 -0
  1174. package/dist/esm/symlinker/frontmatter.js +20 -0
  1175. package/dist/esm/symlinker/index.d.ts +84 -0
  1176. package/dist/esm/symlinker/index.js +496 -0
  1177. package/dist/esm/symlinker/test-utils/assert-symlink-resolves.d.ts +12 -0
  1178. package/dist/esm/symlinker/test-utils/assert-symlink-resolves.js +24 -0
  1179. package/dist/esm/symlinker/toml.d.ts +11 -0
  1180. package/dist/esm/symlinker/toml.js +16 -0
  1181. package/dist/esm/symlinker/unified-sync.d.ts +64 -0
  1182. package/dist/esm/symlinker/unified-sync.js +362 -0
  1183. package/dist/esm/telemetry/_endpoint.d.ts +3 -0
  1184. package/dist/esm/telemetry/_endpoint.js +4 -0
  1185. package/dist/esm/telemetry/setup-tthw.d.ts +10 -0
  1186. package/dist/esm/telemetry/setup-tthw.js +34 -0
  1187. package/dist/esm/test/command-builder.d.ts +25 -0
  1188. package/dist/esm/test/command-builder.js +98 -0
  1189. package/dist/esm/test/index.d.ts +3 -0
  1190. package/dist/esm/test/index.js +3 -0
  1191. package/dist/esm/test/target-resolver.d.ts +13 -0
  1192. package/dist/esm/test/target-resolver.js +53 -0
  1193. package/dist/esm/typecheck/index.d.ts +52 -0
  1194. package/dist/esm/typecheck/index.js +135 -0
  1195. package/dist/esm/vite/bundle-budget.d.ts +37 -0
  1196. package/dist/esm/vite/bundle-budget.js +151 -0
  1197. package/dist/esm/vite/chunk-load-recovery.d.ts +18 -0
  1198. package/dist/esm/vite/chunk-load-recovery.js +62 -0
  1199. package/dist/esm/vite/index.d.ts +3 -0
  1200. package/dist/esm/vite/index.js +3 -0
  1201. package/dist/esm/vite/local.d.ts +16 -0
  1202. package/dist/esm/vite/local.js +164 -0
  1203. package/just/dev-kit.just +24 -0
  1204. package/just/e2e-kit.just +13 -0
  1205. package/just/test-kit.just +10 -0
  1206. package/package.json +675 -0
  1207. package/skills/better-auth-best-practices/SKILL.md +212 -0
  1208. package/skills/deep-research/SKILL.md +240 -0
  1209. package/skills/fix/SKILL.md +120 -0
  1210. package/skills/frontend-design/LICENSE.txt +177 -0
  1211. package/skills/frontend-design/SKILL.md +189 -0
  1212. package/skills/hooks-doctor/SKILL.md +77 -0
  1213. package/skills/logging-best-practices/SKILL.md +145 -0
  1214. package/skills/lore-protocol/SKILL.md +93 -0
  1215. package/skills/plan-refine/SKILL.md +645 -0
  1216. package/skills/pll/SKILL.md +85 -0
  1217. package/skills/react-doctor/SKILL.md +54 -0
  1218. package/skills/systematic-debugging/SKILL.md +322 -0
  1219. package/skills/tanstack-query/SKILL.md +175 -0
  1220. package/skills/tech-debt/SKILL.md +79 -0
  1221. package/skills/test-driven-development/SKILL.md +403 -0
  1222. package/skills/testing-philosophy/SKILL.md +530 -0
  1223. package/skills/vercel-react-best-practices/SKILL.md +212 -0
  1224. package/skills/verify/SKILL.md +133 -0
  1225. package/skills/web-design-guidelines/SKILL.md +53 -0
  1226. package/tsconfig/base.json +37 -0
  1227. package/tsconfig/cloudflare.json +10 -0
  1228. package/tsconfig/library.json +16 -0
  1229. package/tsconfig/react-library.json +9 -0
  1230. package/tsconfig/react-router.json +10 -0
@@ -0,0 +1,2131 @@
1
+ /**
2
+ * Blueprint structured-store MCP server — 8 tools for the blueprint DB.
3
+ *
4
+ * Call `registerBlueprintTools(registrar, cwd)` from server startup.
5
+ * It calls `coldStartIfNeeded` once then registers all 8 tools.
6
+ *
7
+ * All outputs honour the summary-first envelope: { summary, failures, bytes, tokensSaved }
8
+ *
9
+ * Platform-first sync (Task 2.1):
10
+ * When a SyncAdapter is available (credentials present, not disabled), mutations
11
+ * push a BlueprintPlatformEvent before updating local markdown/SQLite.
12
+ * Iron rule: WP_BLUEPRINT_PLATFORM_DISABLED=1 skips the adapter entirely — the
13
+ * markdown-canonical path runs byte-identically to the pre-migration behaviour.
14
+ */
15
+ import { existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
16
+ import { createHash, randomUUID } from 'node:crypto';
17
+ import path from 'node:path';
18
+ import matter from 'gray-matter';
19
+ import { z } from 'zod';
20
+ import { parseBlueprint } from '#core/parser';
21
+ import { openDb } from '#db/connection.js';
22
+ import { resolveBlueprintProjectionDbPath } from '#db/paths.js';
23
+ import { findTemplate } from '#db/templates.js';
24
+ import { resolveBlueprintRoot } from '#utils/blueprint-root.js';
25
+ import { evidenceListSchema, canonicalizeEvidenceList } from '#evidence.js';
26
+ import { checkFreshness, readCurrentHead, readProjectionMetadata, } from '#freshness.js';
27
+ import { applyVerification, assertAllTasksHaveCanonicalPassingEvidence, readTaskVerification, } from '#verification.js';
28
+ import { makeNextAction } from '#next-action.js';
29
+ import { PROJECT_SOURCES } from '#projects.js';
30
+ import { ensureProjectionReady, reIngestProjection } from '#projection-ready.js';
31
+ import { createProjectResolver } from '#project-resolver.js';
32
+ import { aggregateBlueprintRows } from '#aggregate.js';
33
+ import { resolveProjectRoot } from '#mcp/tools/_shared/project-root.js';
34
+ import { maybeHint } from './_tail-hints.js';
35
+ /**
36
+ * Module-level factory. `null` = use the production default (loadSyncCredentials
37
+ * from auth.ts + BlueprintSyncClient + ReplicaManager — lazy-imported so that
38
+ * blueprint-server.ts never statically depends on the HTTP client).
39
+ */
40
+ let _syncAdapterFactory = null;
41
+ /**
42
+ * Override the adapter factory — for tests only.
43
+ * Pass `null` to restore the production default.
44
+ *
45
+ * @internal
46
+ */
47
+ export function _setSyncAdapterFactory(factory) {
48
+ _syncAdapterFactory = factory;
49
+ }
50
+ /**
51
+ * Resolve the sync adapter for the current request.
52
+ *
53
+ * Iron rule: returns `null` when `WP_BLUEPRINT_PLATFORM_DISABLED=1` regardless
54
+ * of any injected factory — the caller must skip all platform operations.
55
+ *
56
+ * @param cwd - repo working directory, used to locate the replica DB file.
57
+ */
58
+ async function resolveSyncAdapter(cwd) {
59
+ if (process.env['WP_BLUEPRINT_PLATFORM_DISABLED'] === '1')
60
+ return null;
61
+ if (_syncAdapterFactory !== null) {
62
+ return _syncAdapterFactory();
63
+ }
64
+ // Production default: lazy-import to avoid coupling the module to the HTTP client.
65
+ // #sync/* resolves via the fallback "#*" → "./src/blueprint/*.ts" mapping.
66
+ const [{ BlueprintSyncClient }, { loadSyncCredentials }, { ReplicaManager }, { openDb: openDbForReplica },] = await Promise.all([
67
+ import('#sync/client.js'),
68
+ import('#sync/auth.js'),
69
+ import('#sync/replica.js'),
70
+ import('#db/connection.js'),
71
+ ]);
72
+ const creds = loadSyncCredentials();
73
+ if (creds === null)
74
+ return null;
75
+ const client = new BlueprintSyncClient(creds);
76
+ // ReplicaManager needs a db handle; store the replica DB in the state root.
77
+ const { getSurfacePath, NotInGitRepoError } = await import('#paths/state-root.js');
78
+ const replicaDbPath = (() => {
79
+ try {
80
+ return getSurfacePath('blueprints/replica.db', 'repo', cwd);
81
+ }
82
+ catch (err) {
83
+ if (err instanceof NotInGitRepoError)
84
+ return path.join(cwd, '.agent', '.replica.db');
85
+ throw err;
86
+ }
87
+ })();
88
+ const conn = openDbForReplica(replicaDbPath);
89
+ const manager = new ReplicaManager({ client, db: conn.db });
90
+ return {
91
+ pushEvent: (event) => client.pushEvent(event),
92
+ ensureFresh: (opts) => manager.ensureFresh(opts),
93
+ };
94
+ }
95
+ const DEFAULT_PLATFORM_MUTATION_TIMEOUT_MS = 5_000;
96
+ function readPlatformMutationTimeoutMs() {
97
+ const parsed = Number.parseInt(process.env['WP_BLUEPRINT_PLATFORM_MUTATION_TIMEOUT_MS'] ??
98
+ String(DEFAULT_PLATFORM_MUTATION_TIMEOUT_MS), 10);
99
+ return Math.max(1, Number.isFinite(parsed) ? parsed : DEFAULT_PLATFORM_MUTATION_TIMEOUT_MS);
100
+ }
101
+ async function awaitPlatformMutationStep(promise, label, timeoutMs) {
102
+ await Promise.race([
103
+ promise,
104
+ new Promise((_, reject) => {
105
+ setTimeout(() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)), timeoutMs);
106
+ }),
107
+ ]);
108
+ }
109
+ async function runPlatformMutationSync(adapter, options) {
110
+ if (adapter === null)
111
+ return;
112
+ const timeoutMs = readPlatformMutationTimeoutMs();
113
+ try {
114
+ if (options.event) {
115
+ await awaitPlatformMutationStep(adapter.pushEvent(options.event), `${options.label} pushEvent`, timeoutMs);
116
+ }
117
+ if (options.ensureFreshSlug) {
118
+ await awaitPlatformMutationStep(adapter.ensureFresh({ slug: options.ensureFreshSlug }), `${options.label} ensureFresh`, timeoutMs);
119
+ }
120
+ }
121
+ catch (error) {
122
+ throw new Error(`${options.label} platform sync failed: ${error instanceof Error ? error.message : toStr(error)}`);
123
+ }
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Constants
127
+ // ---------------------------------------------------------------------------
128
+ const VALIDATE_TS_FILE = '.validate-timestamps.json';
129
+ const ROWS_CAP = 200;
130
+ const DEFAULT_ROOTS_FETCH_TIMEOUT_MS = 750;
131
+ const DEFAULT_PROJECT_DISCOVERY_TIMEOUT_MS = 1_500;
132
+ const LIFECYCLE_ADVICE = 'After creating: /plan-refine to harden; /plan-eng-review to validate; ' +
133
+ 'wp_blueprint_promote draft→planned when ready; /pll for parallel execution; ' +
134
+ '/verify before finalize';
135
+ const ALL_STATES = ['draft', 'planned', 'in-progress', 'parked', 'archived', 'completed'];
136
+ const NON_COMPLETED = ['draft', 'planned', 'in-progress', 'parked', 'archived'];
137
+ const BLUEPRINT_TEMPLATE = `---
138
+ type: blueprint
139
+ title: "{TITLE}"
140
+ status: draft
141
+ complexity: {COMPLEXITY}
142
+ owner: ""
143
+ created: {DATE}
144
+ last_updated: {DATE}
145
+ ---
146
+
147
+ ## Product wedge anchor
148
+
149
+ - **Stage outcome:** <cite roadmap section + specific outcome>
150
+ - **Consuming surface:** <route / component / verb + path>
151
+ - **New user-visible capability:** <one sentence>
152
+
153
+ ## Summary
154
+
155
+ {GOAL}
156
+
157
+ ## Tasks
158
+
159
+ #### Task 1.1: <task title>
160
+
161
+ **Status:** todo
162
+ **Wave:** 0
163
+ **Files:**
164
+ - (path)
165
+
166
+ **Acceptance:**
167
+ - [ ] <criterion>
168
+ `;
169
+ // ---------------------------------------------------------------------------
170
+ // Shared helpers
171
+ // ---------------------------------------------------------------------------
172
+ const dbPath = (cwd) => resolveBlueprintProjectionDbPath(cwd);
173
+ const vtPath = (cwd) => path.join(cwd, '.agent', VALIDATE_TS_FILE);
174
+ const bytes = (s) => Buffer.byteLength(s, 'utf8');
175
+ const toStr = (e) => (e instanceof Error ? e.message : String(e));
176
+ function readBoundedTimeoutMs(envKey, fallback) {
177
+ const parsed = Number.parseInt(process.env[envKey] ?? String(fallback), 10);
178
+ return Math.max(1, Number.isFinite(parsed) ? parsed : fallback);
179
+ }
180
+ async function awaitBounded(promise, timeoutMs) {
181
+ let timeoutId;
182
+ try {
183
+ const value = await Promise.race([
184
+ promise.then((resolved) => ({ timedOut: false, value: resolved })),
185
+ new Promise((resolve) => {
186
+ timeoutId = setTimeout(() => resolve({ timedOut: true }), timeoutMs);
187
+ }),
188
+ ]);
189
+ return value;
190
+ }
191
+ finally {
192
+ if (timeoutId)
193
+ clearTimeout(timeoutId);
194
+ }
195
+ }
196
+ function jsonContent(payload, isError = false) {
197
+ return {
198
+ content: [{ type: 'text', text: JSON.stringify(payload) }],
199
+ structuredContent: payload,
200
+ isError,
201
+ };
202
+ }
203
+ function parseStructuredJson(result) {
204
+ if (result.structuredContent && typeof result.structuredContent === 'object') {
205
+ return result.structuredContent;
206
+ }
207
+ const text = result.content.find((item) => item.type === 'text');
208
+ if (!text || typeof text.text !== 'string')
209
+ return {};
210
+ try {
211
+ return JSON.parse(text.text);
212
+ }
213
+ catch {
214
+ return {};
215
+ }
216
+ }
217
+ function err(summary, error) {
218
+ return jsonContent({ summary, failures: [error], bytes: 0, tokensSaved: 0 }, true);
219
+ }
220
+ function readVt(cwd) {
221
+ try {
222
+ return JSON.parse(readFileSync(vtPath(cwd), 'utf8'));
223
+ }
224
+ catch {
225
+ return {};
226
+ }
227
+ }
228
+ function writeVt(cwd, d) {
229
+ mkdirSync(path.dirname(vtPath(cwd)), { recursive: true });
230
+ writeFileSync(vtPath(cwd), JSON.stringify(d, null, 2), 'utf8');
231
+ }
232
+ function titleToSlug(t) {
233
+ return t
234
+ .toLowerCase()
235
+ .replace(/[^a-z0-9]+/g, '-')
236
+ .replace(/^-|-$/g, '')
237
+ .slice(0, 80);
238
+ }
239
+ function openDbRW(cwd) {
240
+ return openDb(dbPath(cwd));
241
+ }
242
+ async function reIngest(cwd) {
243
+ await reIngestProjection(cwd);
244
+ }
245
+ function findBlueprintDir(blueprintRoot, slug, states) {
246
+ for (const state of states) {
247
+ const d = path.join(blueprintRoot, state, slug);
248
+ if (existsSync(d))
249
+ return { dir: d, state };
250
+ }
251
+ return null;
252
+ }
253
+ function hasRecentAuditFinding(cwd) {
254
+ const file = path.join(cwd, '.agent', '.tail-hint-history.jsonl');
255
+ if (!existsSync(file))
256
+ return false;
257
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
258
+ return readFileSync(file, 'utf8')
259
+ .split('\n')
260
+ .some((l) => {
261
+ try {
262
+ const r = JSON.parse(l);
263
+ return r.hintId === 'AUDIT_FIX' && typeof r.ts === 'number' && r.ts >= cutoff;
264
+ }
265
+ catch {
266
+ return false;
267
+ }
268
+ });
269
+ }
270
+ function appendHint(payload, cwd, hintId) {
271
+ const h = maybeHint(cwd, hintId);
272
+ if (h)
273
+ payload['tail_hint'] = h;
274
+ }
275
+ function projectCandidateView(project) {
276
+ return {
277
+ project_id: project.project_id,
278
+ label: project.label,
279
+ worktree_path: project.worktree_path,
280
+ repo_path: project.repo_path,
281
+ source: project.source,
282
+ has_blueprints: project.has_blueprints,
283
+ };
284
+ }
285
+ function projectDisambiguationError(summary, hint, projects) {
286
+ return jsonContent({
287
+ summary,
288
+ failures: [hint],
289
+ next_action: {
290
+ ...makeNextAction('disambiguate_slug', hint),
291
+ candidates: projects.map(projectCandidateView),
292
+ },
293
+ bytes: 0,
294
+ tokensSaved: 0,
295
+ }, true);
296
+ }
297
+ function resolveFallbackProjectCwd(cwd) {
298
+ try {
299
+ return realpathSync(resolveProjectRoot({ cwd, env: process.env }));
300
+ }
301
+ catch {
302
+ try {
303
+ return realpathSync(cwd);
304
+ }
305
+ catch {
306
+ return cwd;
307
+ }
308
+ }
309
+ }
310
+ function buildFallbackCurrentProject(cwd) {
311
+ const worktreePath = resolveFallbackProjectCwd(cwd);
312
+ const blueprintRoot = resolveBlueprintRoot(worktreePath);
313
+ const hasBlueprints = existsSync(blueprintRoot) && (() => statSync(blueprintRoot).isDirectory())();
314
+ return {
315
+ project_id: worktreePath,
316
+ label: path.basename(worktreePath) || worktreePath,
317
+ repo_path: worktreePath,
318
+ worktree_path: worktreePath,
319
+ source: PROJECT_SOURCES.current,
320
+ has_blueprints: hasBlueprints,
321
+ db_path: dbPath(worktreePath),
322
+ };
323
+ }
324
+ async function resolveToolProject(projectResolver, cwd, projectId) {
325
+ const timed = await awaitBounded(projectResolver.resolve({ cwd, projectId }), readBoundedTimeoutMs('WP_BLUEPRINT_PROJECT_DISCOVERY_TIMEOUT_MS', DEFAULT_PROJECT_DISCOVERY_TIMEOUT_MS));
326
+ if (timed.timedOut) {
327
+ if (projectId === undefined)
328
+ return { cwd: resolveFallbackProjectCwd(cwd), project_id: null };
329
+ try {
330
+ return { cwd: realpathSync(projectId), project_id: null };
331
+ }
332
+ catch {
333
+ return projectDisambiguationError('Project discovery timed out', 'Project discovery timed out. Retry with an explicit project path or call wp_blueprint_projects for a narrower target.', []);
334
+ }
335
+ }
336
+ const resolved = timed.value;
337
+ if (resolved.ok)
338
+ return { cwd: resolved.cwd, project_id: resolved.project_id };
339
+ return projectDisambiguationError(resolved.summary, resolved.hint, resolved.candidates);
340
+ }
341
+ function finishPayload(payload) {
342
+ payload['bytes'] = bytes(JSON.stringify(payload));
343
+ return jsonContent(payload);
344
+ }
345
+ function sortKeys(value) {
346
+ if (Array.isArray(value))
347
+ return value.map(sortKeys);
348
+ if (value !== null && typeof value === 'object') {
349
+ const entries = Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
350
+ const out = {};
351
+ for (const [key, nested] of entries)
352
+ out[key] = sortKeys(nested);
353
+ return out;
354
+ }
355
+ return value;
356
+ }
357
+ function hashMutationPayload(payload) {
358
+ return createHash('sha256')
359
+ .update(JSON.stringify(sortKeys(payload)))
360
+ .digest('hex');
361
+ }
362
+ function mutationFreshnessError(toolName, guidanceTool) {
363
+ return jsonContent({
364
+ summary: `${toolName} rejected a stale mutation token`,
365
+ failures: [
366
+ 'head_at_ingest does not match the current repository HEAD. Refresh blueprint state before mutating.',
367
+ ],
368
+ error: 'stale_head_at_ingest',
369
+ next_action: makeNextAction('reingest_project', `Refresh projection state, then call ${guidanceTool} again to obtain a fresh head_at_ingest token.`),
370
+ bytes: 0,
371
+ tokensSaved: 0,
372
+ }, true);
373
+ }
374
+ function validateMutationFreshnessToken(projectCwd, headAtIngest, toolName, guidanceTool) {
375
+ if (headAtIngest === undefined)
376
+ return null;
377
+ const currentHead = readCurrentHead(projectCwd);
378
+ if (headAtIngest === currentHead)
379
+ return null;
380
+ return mutationFreshnessError(toolName, guidanceTool);
381
+ }
382
+ function readMutationReplay(cwd, toolName, requestId, payloadHash) {
383
+ const target = dbPath(cwd);
384
+ if (!existsSync(target))
385
+ return null;
386
+ const conn = openDb(target);
387
+ try {
388
+ const row = conn.db
389
+ .prepare(`SELECT payload_hash, response_json
390
+ FROM mutation_request_ledger
391
+ WHERE tool_name = ? AND request_id = ?
392
+ LIMIT 1`)
393
+ .get(toolName, requestId) ?? null;
394
+ if (row === null)
395
+ return null;
396
+ if (row.payload_hash !== payloadHash) {
397
+ return err(`${toolName} failed`, `request_id "${requestId}" was already used with a different payload`);
398
+ }
399
+ const payload = JSON.parse(row.response_json);
400
+ payload['idempotent'] = true;
401
+ return finishPayload(payload);
402
+ }
403
+ finally {
404
+ conn.close();
405
+ }
406
+ }
407
+ function recordMutationReplay(cwd, toolName, requestId, payloadHash, payload) {
408
+ const conn = openDbRW(cwd);
409
+ try {
410
+ conn.db
411
+ .prepare(`INSERT OR REPLACE INTO mutation_request_ledger
412
+ (tool_name, request_id, payload_hash, response_json)
413
+ VALUES (?, ?, ?, ?)`)
414
+ .run(toolName, requestId, payloadHash, JSON.stringify(payload));
415
+ }
416
+ finally {
417
+ conn.close();
418
+ }
419
+ }
420
+ // ---------------------------------------------------------------------------
421
+ // Validate logic (shared by handler + promote guard)
422
+ // ---------------------------------------------------------------------------
423
+ function runValidate(filePath) {
424
+ if (!existsSync(filePath))
425
+ return { valid: false, gaps: [`File not found: ${filePath}`] };
426
+ let raw;
427
+ try {
428
+ raw = readFileSync(filePath, 'utf8');
429
+ }
430
+ catch (e) {
431
+ return { valid: false, gaps: [`Cannot read: ${toStr(e)}`] };
432
+ }
433
+ const gaps = [];
434
+ let fm;
435
+ try {
436
+ fm = matter(raw);
437
+ }
438
+ catch (e) {
439
+ return { valid: false, gaps: [`Frontmatter parse error: ${toStr(e)}`] };
440
+ }
441
+ for (const f of ['type', 'title', 'status', 'complexity', 'owner']) {
442
+ const v = fm.data[f];
443
+ if (!v || String(v).trim() === '')
444
+ gaps.push(`Missing or empty frontmatter field: ${f}`);
445
+ }
446
+ const body = fm.content;
447
+ const taskHeaderRegex = /^####\s+(?:\[[^\]]+\]\s+)?Task\s+\S/m;
448
+ if (!taskHeaderRegex.test(body))
449
+ gaps.push('No "#### Task" sections found');
450
+ for (const block of body
451
+ .split(/(?=^####\s+(?:\[[^\]]+\]\s+)?Task\s)/m)
452
+ .filter((b) => /^####\s+(?:\[[^\]]+\]\s+)?Task\s/.test(b.trimStart()))) {
453
+ const label = /^####\s+(?:\[[^\]]+\]\s+)?Task\s+([\d.]+[:\s]+.+)/m.exec(block)?.[1]?.trim() ?? '(unknown)';
454
+ if (!block.includes('**Acceptance:**') && !block.includes('**Acceptance criteria:**'))
455
+ gaps.push(`Task "${label}" is missing **Acceptance:** subsection`);
456
+ }
457
+ if (!/##\s+Product wedge anchor/.test(body))
458
+ gaps.push('Missing "## Product wedge anchor" section');
459
+ return { valid: gaps.length === 0, gaps };
460
+ }
461
+ // ---------------------------------------------------------------------------
462
+ // Tool handlers
463
+ // ---------------------------------------------------------------------------
464
+ const querySchema = z.object({
465
+ template_id: z.string(),
466
+ params: z.record(z.string(), z.unknown()).default({}),
467
+ });
468
+ async function handleQuery(cwd, raw) {
469
+ const p = querySchema.safeParse(raw);
470
+ if (!p.success)
471
+ return err('wp_blueprint_query validation error', p.error.message);
472
+ const { template_id, params } = p.data;
473
+ const tmpl = findTemplate(template_id);
474
+ if (!tmpl)
475
+ return err(`Unknown query template: ${template_id}`, `Template "${template_id}" not found.`);
476
+ try {
477
+ await ensureProjectionReady(cwd);
478
+ const conn = openDbRW(cwd);
479
+ let rows;
480
+ try {
481
+ rows = conn.db.prepare(tmpl.sql).all(...Object.values(params));
482
+ }
483
+ finally {
484
+ conn.close();
485
+ }
486
+ const capped = rows.slice(0, ROWS_CAP);
487
+ const text = JSON.stringify(capped);
488
+ const b = bytes(text);
489
+ return jsonContent({
490
+ summary: `Query "${template_id}" returned ${rows.length} rows (cap ${ROWS_CAP})`,
491
+ rows_capped: capped.length,
492
+ rows: capped,
493
+ failures: [],
494
+ bytes: b,
495
+ tokensSaved: Math.max(0, b - bytes(JSON.stringify(rows))),
496
+ });
497
+ }
498
+ catch (e) {
499
+ return err(`Query "${template_id}" failed`, toStr(e));
500
+ }
501
+ }
502
+ const newSchema = z.object({
503
+ title: z.string(),
504
+ complexity: z.enum(['XS', 'S', 'M', 'L', 'XL']).default('M'),
505
+ goal_prompt: z.string(),
506
+ examples_count: z.number().int().min(0).max(5).default(3),
507
+ });
508
+ async function handleNew(cwd, raw) {
509
+ const p = newSchema.safeParse(raw);
510
+ if (!p.success)
511
+ return err('wp_blueprint_new validation error', p.error.message);
512
+ const { title, complexity, goal_prompt, examples_count } = p.data;
513
+ const today = new Date().toISOString().split('T')[0] ?? '';
514
+ const template = BLUEPRINT_TEMPLATE.replace(/{TITLE}/g, title)
515
+ .replace(/{COMPLEXITY}/g, complexity)
516
+ .replace(/{DATE}/g, today)
517
+ .replace('{GOAL}', goal_prompt);
518
+ const rulesFile = path.join(cwd, '.agent', 'rules', 'blueprint-scoping.md');
519
+ const rulesContext = existsSync(rulesFile) ? readFileSync(rulesFile, 'utf8') : null;
520
+ const examples = [];
521
+ const target = dbPath(cwd);
522
+ if (existsSync(target)) {
523
+ try {
524
+ const conn = openDb(target);
525
+ try {
526
+ examples.push(...conn.db
527
+ .prepare(`SELECT slug, title, complexity FROM blueprints WHERE status = 'completed' AND complexity = ? ORDER BY ingested_at DESC LIMIT ?`)
528
+ .all(complexity, examples_count));
529
+ }
530
+ finally {
531
+ conn.close();
532
+ }
533
+ }
534
+ catch {
535
+ /* non-fatal */
536
+ }
537
+ }
538
+ const b = bytes(template);
539
+ const slug = titleToSlug(title);
540
+ const targetPath = path.join(resolveBlueprintRoot(cwd), 'draft', slug, '_overview.md');
541
+ // Platform-first path: push event to register the blueprint before returning the scaffold.
542
+ // Iron rule: resolveSyncAdapter() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
543
+ const adapter = await resolveSyncAdapter(cwd);
544
+ try {
545
+ await runPlatformMutationSync(adapter, {
546
+ label: 'wp_blueprint_new',
547
+ event: {
548
+ eventId: randomUUID(),
549
+ repoId: process.env['WP_BLUEPRINT_PLATFORM_REPO_ID'] ?? 'local',
550
+ occurredAt: new Date().toISOString(),
551
+ type: 'blueprint.created',
552
+ payload: {
553
+ type: 'blueprint.created',
554
+ slug,
555
+ title,
556
+ complexity,
557
+ status: 'draft',
558
+ },
559
+ },
560
+ });
561
+ }
562
+ catch (e) {
563
+ return err('wp_blueprint_new failed', toStr(e));
564
+ }
565
+ return jsonContent({
566
+ summary: `Blueprint bundle for "${title}" (complexity ${complexity})`,
567
+ target_path: targetPath,
568
+ template,
569
+ rules_context: rulesContext,
570
+ examples,
571
+ lifecycle_advice: LIFECYCLE_ADVICE,
572
+ validation_required: true,
573
+ failures: [],
574
+ bytes: b,
575
+ tokensSaved: 0,
576
+ });
577
+ }
578
+ const validateSchema = z.object({ path: z.string() });
579
+ async function handleValidate(cwd, raw) {
580
+ const p = validateSchema.safeParse(raw);
581
+ if (!p.success)
582
+ return err('wp_blueprint_validate validation error', p.error.message);
583
+ const { path: filePath } = p.data;
584
+ const result = runValidate(filePath);
585
+ if (result.valid) {
586
+ const ts = readVt(cwd);
587
+ ts[path.basename(path.dirname(filePath))] = Date.now();
588
+ writeVt(cwd, ts);
589
+ }
590
+ const b = bytes(JSON.stringify(result));
591
+ return jsonContent({
592
+ summary: result.valid
593
+ ? `Blueprint at ${filePath} is valid`
594
+ : `Blueprint at ${filePath} has ${result.gaps.length} gap(s)`,
595
+ valid: result.valid,
596
+ gaps: result.gaps,
597
+ failures: result.gaps,
598
+ bytes: b,
599
+ tokensSaved: 0,
600
+ });
601
+ }
602
+ const taskNextSchema = z.object({
603
+ blueprint: z.string().optional(),
604
+ project_id: z.string().optional(),
605
+ });
606
+ async function handleTaskNext(projectResolver, cwd, raw) {
607
+ const p = taskNextSchema.safeParse(raw);
608
+ if (!p.success)
609
+ return err('wp_blueprint_task_next validation error', p.error.message);
610
+ const { blueprint, project_id } = p.data;
611
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
612
+ if ('content' in resolvedProject)
613
+ return resolvedProject;
614
+ const projectCwd = resolvedProject.cwd;
615
+ await ensureProjectionReady(projectCwd);
616
+ const failures = [];
617
+ // Platform-first: refresh local replica before reading so the result reflects remote state.
618
+ // Iron rule: resolveSyncAdapter() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
619
+ const adapter = await resolveSyncAdapter(projectCwd);
620
+ if (adapter !== null) {
621
+ const timeoutMs = Math.max(1, Number.parseInt(process.env['WP_BLUEPRINT_READ_FRESH_TIMEOUT_MS'] ?? '5000', 10) || 5000);
622
+ try {
623
+ await Promise.race([
624
+ adapter.ensureFresh(blueprint !== undefined ? { slug: blueprint } : undefined),
625
+ new Promise((_, reject) => {
626
+ setTimeout(() => reject(new Error(`ensureFresh timed out after ${timeoutMs}ms during wp_blueprint_task_next`)), timeoutMs);
627
+ }),
628
+ ]);
629
+ }
630
+ catch (error) {
631
+ failures.push(`Platform freshness refresh skipped: ${error instanceof Error ? error.message : toStr(error)}`);
632
+ }
633
+ }
634
+ const target = dbPath(projectCwd);
635
+ if (!existsSync(target))
636
+ return jsonContent({
637
+ summary: 'No blueprint DB found',
638
+ task: null,
639
+ failures,
640
+ bytes: 0,
641
+ tokensSaved: 0,
642
+ });
643
+ const taskNextFreshness = checkFreshness({ worktree_path: projectCwd, db_path: target });
644
+ if (!taskNextFreshness.ok) {
645
+ return staleProjectionResponse('Blueprint projection is stale', taskNextFreshness.next_action, {
646
+ task: null,
647
+ });
648
+ }
649
+ try {
650
+ const conn = openDb(target);
651
+ const sc = blueprint ? 'AND t.blueprint_slug = ?' : '';
652
+ const readySql = `SELECT t.id, t.blueprint_slug, t.task_id, t.wave, t.lane, t.title, t.status FROM tasks t WHERE t.status = 'todo' ${sc} AND NOT EXISTS (SELECT 1 FROM task_dependencies td JOIN tasks dep ON dep.id = td.depends_on_task_id WHERE td.task_id = t.id AND dep.status != 'done') ORDER BY t.wave, t.id LIMIT 1`;
653
+ const w0Sql = `SELECT COUNT(*) as cnt FROM tasks t WHERE t.status = 'todo' AND t.wave = '0' ${sc} AND NOT EXISTS (SELECT 1 FROM task_dependencies td JOIN tasks dep ON dep.id = td.depends_on_task_id WHERE td.task_id = t.id AND dep.status != 'done')`;
654
+ let task;
655
+ let w0cnt;
656
+ let files;
657
+ try {
658
+ const args = blueprint ? [blueprint] : [];
659
+ task =
660
+ (blueprint
661
+ ? conn.db.prepare(readySql).all(blueprint)
662
+ : conn.db.prepare(readySql).all())[0] ?? null;
663
+ w0cnt =
664
+ (blueprint
665
+ ? conn.db.prepare(w0Sql).all(blueprint)
666
+ : conn.db.prepare(w0Sql).all())[0]?.cnt ?? 0;
667
+ files = task
668
+ ? conn.db
669
+ .prepare('SELECT file_path, op FROM task_files WHERE task_id = ?')
670
+ .all(task.id)
671
+ : [];
672
+ void args;
673
+ }
674
+ finally {
675
+ conn.close();
676
+ }
677
+ const payload = {
678
+ summary: task ? `Next ready task: ${task.task_id} — ${task.title}` : 'No ready tasks found',
679
+ task: task
680
+ ? {
681
+ id: task.id,
682
+ lane: task.lane,
683
+ title: task.title,
684
+ files,
685
+ deps_satisfied: true,
686
+ blueprint_slug: task.blueprint_slug,
687
+ task_id: task.task_id,
688
+ wave: task.wave,
689
+ }
690
+ : null,
691
+ failures,
692
+ bytes: 0,
693
+ tokensSaved: 0,
694
+ };
695
+ if (w0cnt >= 3)
696
+ appendHint(payload, projectCwd, 'PLL_PARALLEL');
697
+ return finishPayload(payload);
698
+ }
699
+ catch (e) {
700
+ return err('wp_blueprint_task_next failed', toStr(e));
701
+ }
702
+ }
703
+ const advanceSchema = z.object({
704
+ project_id: z.string(),
705
+ task_id: z.string(),
706
+ to: z.enum(['todo', 'in-progress', 'blocked', 'done', 'dropped']),
707
+ request_id: z.string().min(1).optional(),
708
+ head_at_ingest: z.string().nullable().optional(),
709
+ });
710
+ async function handleTaskAdvance(projectResolver, cwd, raw) {
711
+ const p = advanceSchema.safeParse(raw);
712
+ if (!p.success)
713
+ return err('wp_blueprint_task_advance validation error', p.error.message);
714
+ const { project_id, task_id, to, request_id, head_at_ingest } = p.data;
715
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
716
+ if ('content' in resolvedProject)
717
+ return resolvedProject;
718
+ const projectCwd = resolvedProject.cwd;
719
+ await ensureProjectionReady(projectCwd);
720
+ const freshnessFailure = validateMutationFreshnessToken(projectCwd, head_at_ingest, 'wp_blueprint_task_advance', 'wp_blueprint_list');
721
+ if (freshnessFailure)
722
+ return freshnessFailure;
723
+ const payloadHash = hashMutationPayload({ task_id, to });
724
+ const replay = request_id !== undefined
725
+ ? readMutationReplay(projectCwd, 'wp_blueprint_task_advance', request_id, payloadHash)
726
+ : null;
727
+ if (replay)
728
+ return replay;
729
+ // Task 3.2 guard: refuse to mark done via advance — require evidence via wp_blueprint_task_verify
730
+ if (to === 'done') {
731
+ return jsonContent({
732
+ summary: 'Use wp_blueprint_task_verify to mark tasks done with evidence',
733
+ failures: ['Use wp_blueprint_task_verify to mark tasks done with evidence'],
734
+ error: 'Use wp_blueprint_task_verify to mark tasks done with evidence',
735
+ next_action: makeNextAction('verify_task', 'Call wp_blueprint_task_verify with evidence items'),
736
+ bytes: 0,
737
+ tokensSaved: 0,
738
+ }, true);
739
+ }
740
+ const target = dbPath(projectCwd);
741
+ if (!existsSync(target))
742
+ return err('wp_blueprint_task_advance failed', 'Blueprint DB not found');
743
+ try {
744
+ const conn = openDb(target);
745
+ let oldStatus = null;
746
+ let filePath = null;
747
+ let blueprintSlug = null;
748
+ try {
749
+ const row = conn.db
750
+ .prepare('SELECT status, blueprint_slug FROM tasks WHERE task_id = ? LIMIT 1')
751
+ .get(task_id);
752
+ if (!row)
753
+ return err('wp_blueprint_task_advance failed', `Task "${task_id}" not found in DB`);
754
+ oldStatus = row.status;
755
+ blueprintSlug = row.blueprint_slug;
756
+ const bp = conn.db
757
+ .prepare('SELECT file_path FROM blueprints WHERE slug = ?')
758
+ .get(row.blueprint_slug);
759
+ if (bp?.file_path)
760
+ filePath = bp.file_path;
761
+ }
762
+ finally {
763
+ conn.close();
764
+ }
765
+ // Platform-first path: push event + pull fresh replica before local update.
766
+ // Iron rule: resolveSyncAdapter() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
767
+ const adapter = await resolveSyncAdapter(projectCwd);
768
+ if (blueprintSlug !== null && oldStatus !== null) {
769
+ try {
770
+ await runPlatformMutationSync(adapter, {
771
+ label: 'wp_blueprint_task_advance',
772
+ event: {
773
+ eventId: randomUUID(),
774
+ repoId: process.env['WP_BLUEPRINT_PLATFORM_REPO_ID'] ?? 'local',
775
+ occurredAt: new Date().toISOString(),
776
+ type: 'task.status_changed',
777
+ payload: {
778
+ type: 'task.status_changed',
779
+ blueprintSlug,
780
+ taskId: task_id,
781
+ fromStatus: oldStatus,
782
+ toStatus: to,
783
+ },
784
+ },
785
+ ensureFreshSlug: blueprintSlug,
786
+ });
787
+ }
788
+ catch (e) {
789
+ return err('wp_blueprint_task_advance failed', toStr(e));
790
+ }
791
+ }
792
+ // Always update local markdown + SQLite.
793
+ // Platform-first: these become derived artifacts; disabled: these are canonical.
794
+ if (filePath && existsSync(filePath)) {
795
+ const lines = readFileSync(filePath, 'utf8').split('\n');
796
+ let inBlock = false;
797
+ for (let i = 0; i < lines.length; i++) {
798
+ const line = lines[i] ?? '';
799
+ if (line.match(new RegExp(`#### Task\\s+${task_id.replace(/\./g, '\\.')}`)))
800
+ inBlock = true;
801
+ else if (inBlock && line.startsWith('#### '))
802
+ break;
803
+ else if (inBlock && line.startsWith('**Status:**')) {
804
+ lines[i] = `**Status:** ${to}`;
805
+ break;
806
+ }
807
+ }
808
+ writeFileSync(filePath, lines.join('\n'), 'utf8');
809
+ }
810
+ try {
811
+ await reIngest(projectCwd);
812
+ }
813
+ catch {
814
+ /* non-fatal */
815
+ }
816
+ const payload = {
817
+ summary: `Task "${task_id}" advanced from "${oldStatus}" to "${to}"`,
818
+ task_id,
819
+ old_status: oldStatus,
820
+ new_status: to,
821
+ idempotent: false,
822
+ failures: [],
823
+ bytes: 0,
824
+ tokensSaved: 0,
825
+ };
826
+ if (request_id !== undefined) {
827
+ recordMutationReplay(projectCwd, 'wp_blueprint_task_advance', request_id, payloadHash, payload);
828
+ }
829
+ return finishPayload(payload);
830
+ }
831
+ catch (e) {
832
+ return err('wp_blueprint_task_advance failed', toStr(e));
833
+ }
834
+ }
835
+ // Task 3.2 — wp_blueprint_task_verify
836
+ const taskVerifySchema = z.object({
837
+ project_id: z.string(),
838
+ slug: z.string(),
839
+ task_id: z.string(),
840
+ evidence: evidenceListSchema,
841
+ request_id: z.string().min(1).optional(),
842
+ head_at_ingest: z.string().nullable().optional(),
843
+ });
844
+ async function handleTaskVerify(projectResolver, cwd, raw) {
845
+ const p = taskVerifySchema.safeParse(raw);
846
+ if (!p.success)
847
+ return err('wp_blueprint_task_verify validation error', p.error.message);
848
+ const { project_id, slug, task_id, evidence, request_id, head_at_ingest } = p.data;
849
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
850
+ if ('content' in resolvedProject)
851
+ return resolvedProject;
852
+ const projectCwd = resolvedProject.cwd;
853
+ await ensureProjectionReady(projectCwd);
854
+ const freshnessFailure = validateMutationFreshnessToken(projectCwd, head_at_ingest, 'wp_blueprint_task_verify', 'wp_blueprint_get');
855
+ if (freshnessFailure)
856
+ return freshnessFailure;
857
+ const payloadHash = hashMutationPayload({ slug, task_id, evidence });
858
+ const replay = request_id !== undefined
859
+ ? readMutationReplay(projectCwd, 'wp_blueprint_task_verify', request_id, payloadHash)
860
+ : null;
861
+ if (replay)
862
+ return replay;
863
+ // Locate the blueprint markdown file on disk
864
+ const root = resolveBlueprintRoot(projectCwd);
865
+ const found = findBlueprintDir(root, slug, ALL_STATES);
866
+ if (!found) {
867
+ return err('wp_blueprint_task_verify failed', `Blueprint "${slug}" not found in any state directory`);
868
+ }
869
+ const filePath = path.join(found.dir, '_overview.md');
870
+ if (!existsSync(filePath)) {
871
+ return err('wp_blueprint_task_verify failed', `Blueprint overview not found at ${filePath}`);
872
+ }
873
+ const markdownBefore = readFileSync(filePath, 'utf8');
874
+ // Idempotency check: if the task already has the same canonical evidence block, skip write.
875
+ // We check this BEFORE calling applyVerification to avoid whitespace normalization drift
876
+ // making `result.markdown !== markdownBefore` always true even for identical evidence.
877
+ const incomingCanonical = canonicalizeEvidenceList(evidence);
878
+ const existingEvidence = readTaskVerification(markdownBefore, task_id);
879
+ if (existingEvidence !== null &&
880
+ canonicalizeEvidenceList(existingEvidence) === incomingCanonical) {
881
+ const nextPayload = parseStructuredJson(await handleTaskNext(projectResolver, projectCwd, {
882
+ blueprint: slug,
883
+ project_id: resolvedProject.project_id ?? projectCwd,
884
+ }));
885
+ const payload = {
886
+ summary: `Task "${task_id}" verification is already recorded (idempotent)`,
887
+ status: 'done',
888
+ idempotent: true,
889
+ next_summary: typeof nextPayload['summary'] === 'string'
890
+ ? nextPayload['summary']
891
+ : 'No ready tasks found',
892
+ next_task: typeof nextPayload['task'] === 'object' && nextPayload['task'] !== null
893
+ ? nextPayload['task']
894
+ : null,
895
+ failures: [],
896
+ bytes: bytes(markdownBefore),
897
+ tokensSaved: 0,
898
+ };
899
+ if (request_id !== undefined) {
900
+ recordMutationReplay(projectCwd, 'wp_blueprint_task_verify', request_id, payloadHash, payload);
901
+ }
902
+ return finishPayload(payload);
903
+ }
904
+ // Apply verification (pure function — no FS side effects)
905
+ const result = applyVerification(markdownBefore, task_id, evidence);
906
+ if (!result.ok) {
907
+ return jsonContent({
908
+ summary: 'Verification failed',
909
+ failures: result.failures,
910
+ next_action: makeNextAction('verify_task', result.failures[0] ?? 'Verification failed'),
911
+ bytes: 0,
912
+ tokensSaved: 0,
913
+ }, true);
914
+ }
915
+ // Write updated markdown back to disk
916
+ writeFileSync(filePath, result.markdown, 'utf8');
917
+ // Re-ingest so the DB projection reflects the completed status
918
+ try {
919
+ await reIngest(projectCwd);
920
+ }
921
+ catch {
922
+ /* non-fatal */
923
+ }
924
+ const b = bytes(result.markdown);
925
+ const nextPayload = parseStructuredJson(await handleTaskNext(projectResolver, projectCwd, {
926
+ blueprint: slug,
927
+ project_id: resolvedProject.project_id ?? projectCwd,
928
+ }));
929
+ const payload = {
930
+ summary: `Task "${task_id}" verified and marked done`,
931
+ status: 'done',
932
+ idempotent: false,
933
+ next_summary: typeof nextPayload['summary'] === 'string' ? nextPayload['summary'] : 'No ready tasks found',
934
+ next_task: typeof nextPayload['task'] === 'object' && nextPayload['task'] !== null
935
+ ? nextPayload['task']
936
+ : null,
937
+ failures: [],
938
+ bytes: b,
939
+ tokensSaved: 0,
940
+ };
941
+ if (request_id !== undefined) {
942
+ recordMutationReplay(projectCwd, 'wp_blueprint_task_verify', request_id, payloadHash, payload);
943
+ }
944
+ return finishPayload(payload);
945
+ }
946
+ const promoteSchema = z.object({
947
+ project_id: z.string().optional(),
948
+ slug: z.string(),
949
+ to_state: z.enum(['planned', 'in-progress', 'completed', 'parked', 'archived']),
950
+ });
951
+ async function handlePromote(projectResolver, cwd, raw) {
952
+ const p = promoteSchema.safeParse(raw);
953
+ if (!p.success)
954
+ return err('wp_blueprint_promote validation error', p.error.message);
955
+ const { project_id, slug, to_state } = p.data;
956
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
957
+ if ('content' in resolvedProject)
958
+ return resolvedProject;
959
+ const projectCwd = resolvedProject.cwd;
960
+ const root = resolveBlueprintRoot(projectCwd);
961
+ const found = findBlueprintDir(root, slug, ALL_STATES);
962
+ if (!found)
963
+ return err('wp_blueprint_promote failed', `Blueprint "${slug}" not found in any state directory`);
964
+ const { dir: currentDir, state: currentState } = found;
965
+ const overviewPath = path.join(currentDir, '_overview.md');
966
+ const ts = readVt(projectCwd);
967
+ const mtime = existsSync(overviewPath) ? statSync(overviewPath).mtimeMs : 0;
968
+ if ((ts[slug] ?? 0) < mtime)
969
+ return err('wp_blueprint_promote refused', `Blueprint "${slug}" not validated since last write. Run wp_blueprint_validate first.`);
970
+ if (to_state === 'completed') {
971
+ try {
972
+ assertBlueprintCanComplete(overviewPath, slug);
973
+ }
974
+ catch (error) {
975
+ return err('wp_blueprint_promote refused', toStr(error));
976
+ }
977
+ }
978
+ // Platform-first path: push event + pull fresh replica before local move.
979
+ // Iron rule: resolveSyncAdapter() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
980
+ const adapter = await resolveSyncAdapter(projectCwd);
981
+ try {
982
+ await runPlatformMutationSync(adapter, {
983
+ label: 'wp_blueprint_promote',
984
+ event: {
985
+ eventId: randomUUID(),
986
+ repoId: process.env['WP_BLUEPRINT_PLATFORM_REPO_ID'] ?? 'local',
987
+ occurredAt: new Date().toISOString(),
988
+ type: 'blueprint.status_changed',
989
+ payload: {
990
+ type: 'blueprint.status_changed',
991
+ slug,
992
+ fromStatus: currentState,
993
+ toStatus: to_state,
994
+ },
995
+ },
996
+ ensureFreshSlug: slug,
997
+ });
998
+ }
999
+ catch (e) {
1000
+ return err('wp_blueprint_promote failed', toStr(e));
1001
+ }
1002
+ const { renameSync } = await import('node:fs');
1003
+ const destDir = path.join(root, to_state, slug);
1004
+ mkdirSync(path.dirname(destDir), { recursive: true });
1005
+ try {
1006
+ renameSync(currentDir, destDir);
1007
+ }
1008
+ catch (e) {
1009
+ return err('wp_blueprint_promote failed', `Directory move error: ${toStr(e)}`);
1010
+ }
1011
+ const destOverview = path.join(destDir, '_overview.md');
1012
+ if (existsSync(destOverview)) {
1013
+ const fm = matter(readFileSync(destOverview, 'utf8'));
1014
+ fm.data['status'] = to_state;
1015
+ writeFileSync(destOverview, matter.stringify(fm.content, fm.data), 'utf8');
1016
+ }
1017
+ try {
1018
+ await reIngest(projectCwd);
1019
+ }
1020
+ catch {
1021
+ /* non-fatal */
1022
+ }
1023
+ const payload = {
1024
+ summary: `Blueprint "${slug}" promoted from "${currentState}" to "${to_state}"`,
1025
+ slug,
1026
+ from_state: currentState,
1027
+ to_state,
1028
+ new_path: destOverview,
1029
+ failures: [],
1030
+ bytes: 0,
1031
+ tokensSaved: 0,
1032
+ };
1033
+ if (currentState === 'draft' && to_state === 'planned')
1034
+ appendHint(payload, projectCwd, 'PLAN_REFINE');
1035
+ return finishPayload(payload);
1036
+ }
1037
+ const finalizeSchema = z.object({ project_id: z.string().optional(), slug: z.string() });
1038
+ async function handleFinalize(projectResolver, cwd, raw) {
1039
+ const p = finalizeSchema.safeParse(raw);
1040
+ if (!p.success)
1041
+ return err('wp_blueprint_finalize validation error', p.error.message);
1042
+ const { project_id, slug } = p.data;
1043
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
1044
+ if ('content' in resolvedProject)
1045
+ return resolvedProject;
1046
+ const projectCwd = resolvedProject.cwd;
1047
+ await ensureProjectionReady(projectCwd);
1048
+ const target = dbPath(projectCwd);
1049
+ if (!existsSync(target))
1050
+ return err('wp_blueprint_finalize failed', 'Blueprint DB not found');
1051
+ const conn = openDb(target);
1052
+ let openTasks;
1053
+ try {
1054
+ openTasks = conn.db
1055
+ .prepare(`SELECT task_id, status FROM tasks WHERE blueprint_slug = ? AND status NOT IN ('done', 'dropped')`)
1056
+ .all(slug);
1057
+ }
1058
+ finally {
1059
+ conn.close();
1060
+ }
1061
+ if (openTasks.length > 0)
1062
+ return err('wp_blueprint_finalize refused', `Blueprint "${slug}" has open tasks: ${openTasks.map((t) => `${t.task_id} (${t.status})`).join(', ')}`);
1063
+ const root = resolveBlueprintRoot(projectCwd);
1064
+ const found = findBlueprintDir(root, slug, NON_COMPLETED);
1065
+ if (!found) {
1066
+ const alreadyDone = path.join(root, 'completed', slug);
1067
+ if (existsSync(alreadyDone))
1068
+ return jsonContent({
1069
+ summary: `Blueprint "${slug}" is already in completed`,
1070
+ slug,
1071
+ failures: [],
1072
+ bytes: 0,
1073
+ tokensSaved: 0,
1074
+ });
1075
+ return err('wp_blueprint_finalize failed', `Blueprint "${slug}" not found`);
1076
+ }
1077
+ try {
1078
+ assertBlueprintCanComplete(path.join(found.dir, '_overview.md'), slug);
1079
+ }
1080
+ catch (error) {
1081
+ return err('wp_blueprint_finalize refused', toStr(error));
1082
+ }
1083
+ // Platform-first path: push event + pull fresh replica before local move.
1084
+ // Iron rule: resolveSyncAdapter() returns null when WP_BLUEPRINT_PLATFORM_DISABLED=1.
1085
+ const adapter = await resolveSyncAdapter(projectCwd);
1086
+ try {
1087
+ await runPlatformMutationSync(adapter, {
1088
+ label: 'wp_blueprint_finalize',
1089
+ event: {
1090
+ eventId: randomUUID(),
1091
+ repoId: process.env['WP_BLUEPRINT_PLATFORM_REPO_ID'] ?? 'local',
1092
+ occurredAt: new Date().toISOString(),
1093
+ type: 'blueprint.finalized',
1094
+ payload: {
1095
+ type: 'blueprint.finalized',
1096
+ slug,
1097
+ },
1098
+ },
1099
+ ensureFreshSlug: slug,
1100
+ });
1101
+ }
1102
+ catch (e) {
1103
+ return err('wp_blueprint_finalize failed', toStr(e));
1104
+ }
1105
+ const { renameSync } = await import('node:fs');
1106
+ const destDir = path.join(root, 'completed', slug);
1107
+ mkdirSync(path.dirname(destDir), { recursive: true });
1108
+ try {
1109
+ renameSync(found.dir, destDir);
1110
+ }
1111
+ catch (e) {
1112
+ return err('wp_blueprint_finalize failed', `Directory move error: ${toStr(e)}`);
1113
+ }
1114
+ const destOverview = path.join(destDir, '_overview.md');
1115
+ if (existsSync(destOverview)) {
1116
+ const fm = matter(readFileSync(destOverview, 'utf8'));
1117
+ fm.data['status'] = 'completed';
1118
+ fm.data['completed_at'] = new Date().toISOString().split('T')[0] ?? '';
1119
+ writeFileSync(destOverview, matter.stringify(fm.content, fm.data), 'utf8');
1120
+ }
1121
+ try {
1122
+ await reIngest(projectCwd);
1123
+ }
1124
+ catch {
1125
+ /* non-fatal */
1126
+ }
1127
+ const payload = {
1128
+ summary: `Blueprint "${slug}" finalized and moved to completed`,
1129
+ slug,
1130
+ new_path: destOverview,
1131
+ failures: [],
1132
+ bytes: 0,
1133
+ tokensSaved: 0,
1134
+ };
1135
+ if (hasRecentAuditFinding(projectCwd))
1136
+ appendHint(payload, projectCwd, 'AUDIT_FIX');
1137
+ return finishPayload(payload);
1138
+ }
1139
+ function assertBlueprintCanComplete(overviewPath, slug) {
1140
+ const markdown = readFileSync(overviewPath, 'utf8');
1141
+ const blueprint = parseBlueprint(markdown, slug);
1142
+ const unfinished = blueprint.tasks.filter((task) => task.status !== 'done');
1143
+ if (unfinished.length > 0) {
1144
+ const list = unfinished.map((task) => `${task.id} (${task.status})`).join(', ');
1145
+ throw new Error(`Cannot complete "${slug}": the following tasks are not done: ${list}`);
1146
+ }
1147
+ assertAllTasksHaveCanonicalPassingEvidence(markdown, blueprint.tasks.map((task) => task.id));
1148
+ }
1149
+ const depgraphSchema = z.object({ from: z.string() });
1150
+ async function handleDepgraph(cwd, raw) {
1151
+ const p = depgraphSchema.safeParse(raw);
1152
+ if (!p.success)
1153
+ return err('wp_blueprint_depgraph validation error', p.error.message);
1154
+ const { from } = p.data;
1155
+ await ensureProjectionReady(cwd);
1156
+ const target = dbPath(cwd);
1157
+ if (!existsSync(target))
1158
+ return err('wp_blueprint_depgraph failed', 'Blueprint DB not found');
1159
+ try {
1160
+ const conn = openDb(target);
1161
+ const nodes = new Map();
1162
+ const edges = [];
1163
+ try {
1164
+ const queue = [from];
1165
+ const visited = new Set();
1166
+ while (queue.length > 0) {
1167
+ const slug = queue.shift();
1168
+ if (!slug || visited.has(slug))
1169
+ continue;
1170
+ visited.add(slug);
1171
+ const bp = conn.db
1172
+ .prepare('SELECT slug, title, status FROM blueprints WHERE slug = ?')
1173
+ .get(slug);
1174
+ if (bp)
1175
+ nodes.set(slug, bp);
1176
+ for (const d of conn.db
1177
+ .prepare('SELECT depends_on_slug FROM blueprint_dependencies WHERE blueprint_slug = ?')
1178
+ .all(slug)) {
1179
+ edges.push({ from: slug, to: d.depends_on_slug, type: 'blueprint' });
1180
+ if (!visited.has(d.depends_on_slug))
1181
+ queue.push(d.depends_on_slug);
1182
+ }
1183
+ for (const cd of conn.db
1184
+ .prepare('SELECT target_repo, target_slug, target_slug_hash, is_redacted FROM cross_repo_dependencies WHERE blueprint_slug = ?')
1185
+ .all(slug)) {
1186
+ const to = cd.is_redacted === 1 && cd.target_slug_hash
1187
+ ? `private/${cd.target_slug_hash.slice(0, 12)}`
1188
+ : `${cd.target_repo}/${cd.target_slug ?? '?'}`;
1189
+ edges.push({ from: slug, to, type: 'cross-repo', redacted: cd.is_redacted === 1 });
1190
+ }
1191
+ }
1192
+ }
1193
+ finally {
1194
+ conn.close();
1195
+ }
1196
+ const nodeList = [...nodes.values()];
1197
+ const b = bytes(JSON.stringify({ nodes: nodeList, edges }));
1198
+ return jsonContent({
1199
+ summary: `Dependency graph from "${from}": ${nodeList.length} nodes, ${edges.length} edges`,
1200
+ nodes: nodeList,
1201
+ edges,
1202
+ failures: [],
1203
+ bytes: b,
1204
+ tokensSaved: 0,
1205
+ });
1206
+ }
1207
+ catch (e) {
1208
+ return err('wp_blueprint_depgraph failed', toStr(e));
1209
+ }
1210
+ }
1211
+ // ---------------------------------------------------------------------------
1212
+ // Task 2.2 handlers: list / get / context / create
1213
+ // ---------------------------------------------------------------------------
1214
+ // Zod target schemas (F15/E13)
1215
+ const ReadTarget = z.object({
1216
+ project_id: z.string().optional(),
1217
+ scope: z.enum(['current', 'roots', 'workspace', 'all']).optional(),
1218
+ });
1219
+ const MutationTarget = z.object({
1220
+ project_id: z.string(),
1221
+ // NO scope field — enforced at type level per F15/E13
1222
+ });
1223
+ const listSchema = ReadTarget.extend({
1224
+ status: z.enum(['draft', 'planned', 'in-progress', 'completed', 'parked', 'archived']).optional(),
1225
+ limit: z.number().int().min(1).max(500).default(100),
1226
+ });
1227
+ const listBpReader = ({ db }) => {
1228
+ // Reader used by both single-project and aggregate paths.
1229
+ // Callers layer on status/limit filters after the fact when using aggregate.
1230
+ const sql = `SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints ORDER BY ingested_at DESC LIMIT 500`;
1231
+ return db.prepare(sql).all();
1232
+ };
1233
+ function staleProjectionResponse(summary, nextAction, extra) {
1234
+ return jsonContent({
1235
+ summary,
1236
+ failures: [],
1237
+ bytes: 0,
1238
+ tokensSaved: 0,
1239
+ ...extra,
1240
+ next_action: nextAction,
1241
+ });
1242
+ }
1243
+ function listCurrentProjectBlueprintRows(cwd, options) {
1244
+ const target = dbPath(cwd);
1245
+ if (!existsSync(target))
1246
+ return [];
1247
+ const conn = openDb(target);
1248
+ try {
1249
+ const sql = options.status
1250
+ ? `SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints WHERE status = ? ORDER BY ingested_at DESC LIMIT ?`
1251
+ : `SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints ORDER BY ingested_at DESC LIMIT ?`;
1252
+ return (options.status
1253
+ ? conn.db.prepare(sql).all(options.status, options.limit)
1254
+ : conn.db.prepare(sql).all(options.limit));
1255
+ }
1256
+ finally {
1257
+ conn.close();
1258
+ }
1259
+ }
1260
+ function getCurrentProjectBlueprint(cwd, slug) {
1261
+ const target = dbPath(cwd);
1262
+ if (!existsSync(target))
1263
+ return { blueprint: null, tasks: [] };
1264
+ const conn = openDb(target);
1265
+ try {
1266
+ const blueprint = conn.db
1267
+ .prepare(`SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints WHERE slug = ?`)
1268
+ .get(slug) ?? null;
1269
+ const tasks = blueprint
1270
+ ? conn.db
1271
+ .prepare(`SELECT task_id, title, status, wave, lane FROM tasks WHERE blueprint_slug = ? ORDER BY id`)
1272
+ .all(slug)
1273
+ : [];
1274
+ return { blueprint, tasks };
1275
+ }
1276
+ finally {
1277
+ conn.close();
1278
+ }
1279
+ }
1280
+ async function handleBlueprintList(projectResolver, cwd, raw) {
1281
+ const p = listSchema.safeParse(raw);
1282
+ if (!p.success)
1283
+ return err('wp_blueprint_list validation error', p.error.message);
1284
+ const { status, limit, scope, project_id } = p.data;
1285
+ // Multi-project path: scope is 'roots', 'workspace', or 'all'
1286
+ const isMultiScope = scope === 'roots' || scope === 'workspace' || scope === 'all';
1287
+ if (isMultiScope) {
1288
+ try {
1289
+ const target = { scope };
1290
+ if (project_id)
1291
+ target.project_id = project_id;
1292
+ const timed = await awaitBounded(aggregateBlueprintRows({
1293
+ target,
1294
+ read: listBpReader,
1295
+ resolveOptions: { cwd },
1296
+ }), readBoundedTimeoutMs('WP_BLUEPRINT_PROJECT_DISCOVERY_TIMEOUT_MS', DEFAULT_PROJECT_DISCOVERY_TIMEOUT_MS));
1297
+ if (timed.timedOut) {
1298
+ const fallbackCwd = resolveFallbackProjectCwd(cwd);
1299
+ const rows = listCurrentProjectBlueprintRows(fallbackCwd, { status, limit });
1300
+ const b = bytes(JSON.stringify(rows));
1301
+ return jsonContent({
1302
+ summary: `Project discovery timed out; returning ${rows.length} blueprint(s) from the current project only`,
1303
+ blueprints: rows,
1304
+ failures: ['project_discovery_timeout'],
1305
+ duplicate_slugs: [],
1306
+ freshness_ok: false,
1307
+ bytes: b,
1308
+ tokensSaved: 0,
1309
+ });
1310
+ }
1311
+ const result = timed.value;
1312
+ let rows = result.rows;
1313
+ if (status)
1314
+ rows = rows.filter((r) => r.status === status);
1315
+ rows = rows.slice(0, limit);
1316
+ const b = bytes(JSON.stringify(rows));
1317
+ return jsonContent({
1318
+ summary: `Found ${rows.length} blueprint(s)${status ? ` with status "${status}"` : ''} across ${result.projects.length} project(s)`,
1319
+ blueprints: rows,
1320
+ failures: result.failures,
1321
+ duplicate_slugs: result.duplicate_slugs,
1322
+ freshness_ok: result.failures.length === 0,
1323
+ bytes: b,
1324
+ tokensSaved: 0,
1325
+ });
1326
+ }
1327
+ catch (e) {
1328
+ return err('wp_blueprint_list failed', toStr(e));
1329
+ }
1330
+ }
1331
+ // Single-project path: scope is 'current' or omitted
1332
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
1333
+ if ('content' in resolvedProject)
1334
+ return resolvedProject;
1335
+ const projectCwd = resolvedProject.cwd;
1336
+ await ensureProjectionReady(projectCwd);
1337
+ const target = dbPath(projectCwd);
1338
+ if (!existsSync(target))
1339
+ return jsonContent({
1340
+ summary: 'No blueprint DB found — run wp_blueprint_new or trigger a re-ingest',
1341
+ blueprints: [],
1342
+ freshness_ok: false,
1343
+ next_action: { kind: 'rebuild_db', hint: 'Blueprint DB missing. Re-ingest to create it.' },
1344
+ failures: [],
1345
+ bytes: 0,
1346
+ tokensSaved: 0,
1347
+ });
1348
+ const listFreshness = checkFreshness({ worktree_path: projectCwd, db_path: target });
1349
+ if (!listFreshness.ok) {
1350
+ return staleProjectionResponse('Blueprint projection is stale', listFreshness.next_action, {
1351
+ blueprints: [],
1352
+ project_id: resolvedProject.project_id ?? projectCwd,
1353
+ freshness_ok: false,
1354
+ });
1355
+ }
1356
+ try {
1357
+ const conn = openDb(target);
1358
+ let rows;
1359
+ try {
1360
+ const sql = status
1361
+ ? `SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints WHERE status = ? ORDER BY ingested_at DESC LIMIT ?`
1362
+ : `SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints ORDER BY ingested_at DESC LIMIT ?`;
1363
+ rows = (status
1364
+ ? conn.db.prepare(sql).all(status, limit)
1365
+ : conn.db.prepare(sql).all(limit));
1366
+ }
1367
+ finally {
1368
+ conn.close();
1369
+ }
1370
+ const b = bytes(JSON.stringify(rows));
1371
+ return jsonContent({
1372
+ summary: `Found ${rows.length} blueprint(s)${status ? ` with status "${status}"` : ''}`,
1373
+ blueprints: rows,
1374
+ project_id: resolvedProject.project_id ?? projectCwd,
1375
+ freshness_ok: true,
1376
+ failures: [],
1377
+ bytes: b,
1378
+ tokensSaved: 0,
1379
+ });
1380
+ }
1381
+ catch (e) {
1382
+ return err('wp_blueprint_list failed', toStr(e));
1383
+ }
1384
+ }
1385
+ const getSchema = ReadTarget.extend({ slug: z.string() });
1386
+ async function handleBlueprintGet(projectResolver, cwd, raw) {
1387
+ const p = getSchema.safeParse(raw);
1388
+ if (!p.success)
1389
+ return err('wp_blueprint_get validation error', p.error.message);
1390
+ const { slug, scope, project_id } = p.data;
1391
+ const isMultiScope = scope === 'roots' || scope === 'workspace' || scope === 'all';
1392
+ if (isMultiScope) {
1393
+ try {
1394
+ const readTarget = { scope };
1395
+ if (project_id)
1396
+ readTarget.project_id = project_id;
1397
+ const timed = await awaitBounded(aggregateBlueprintRows({
1398
+ target: readTarget,
1399
+ read: ({ db }) => {
1400
+ const row = db
1401
+ .prepare(`SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints WHERE slug = ?`)
1402
+ .get(slug);
1403
+ return row ? [row] : [];
1404
+ },
1405
+ resolveOptions: { cwd },
1406
+ }), readBoundedTimeoutMs('WP_BLUEPRINT_PROJECT_DISCOVERY_TIMEOUT_MS', DEFAULT_PROJECT_DISCOVERY_TIMEOUT_MS));
1407
+ if (timed.timedOut) {
1408
+ const fallbackCwd = resolveFallbackProjectCwd(cwd);
1409
+ const { blueprint, tasks } = getCurrentProjectBlueprint(fallbackCwd, slug);
1410
+ if (!blueprint) {
1411
+ return jsonContent({
1412
+ summary: `Project discovery timed out before "${slug}" could be searched outside the current project`,
1413
+ blueprint: null,
1414
+ content_hash: null,
1415
+ ingested_at: null,
1416
+ head_at_ingest: null,
1417
+ project_id: fallbackCwd,
1418
+ next_action: makeNextAction('disambiguate_slug', 'Project discovery timed out. Retry with an explicit project_id or a narrower scope.'),
1419
+ failures: ['project_discovery_timeout'],
1420
+ bytes: 0,
1421
+ tokensSaved: 0,
1422
+ });
1423
+ }
1424
+ const blueprintWithTasks = { ...blueprint, tasks };
1425
+ const b = bytes(JSON.stringify(blueprintWithTasks));
1426
+ return jsonContent({
1427
+ summary: `Project discovery timed out; returning current-project match for "${slug}"`,
1428
+ blueprint: blueprintWithTasks,
1429
+ content_hash: blueprint.content_hash,
1430
+ ingested_at: blueprint.ingested_at,
1431
+ head_at_ingest: readProjectionMetadata(dbPath(fallbackCwd))?.head_at_ingest ?? null,
1432
+ project_id: fallbackCwd,
1433
+ failures: ['project_discovery_timeout'],
1434
+ bytes: b,
1435
+ tokensSaved: 0,
1436
+ });
1437
+ }
1438
+ const result = timed.value;
1439
+ // Duplicate slug across projects — caller must disambiguate
1440
+ if (result.duplicate_slugs.includes(slug)) {
1441
+ const candidates = result.rows
1442
+ .filter((r) => r.slug === slug)
1443
+ .map((r) => ({ project_id: r.project_id, file_path: r.file_path }));
1444
+ return jsonContent({
1445
+ summary: `Blueprint "${slug}" found in multiple projects — disambiguation required`,
1446
+ blueprint: null,
1447
+ next_action: {
1448
+ ...makeNextAction('disambiguate_slug', `Slug "${slug}" exists in ${candidates.length} projects. Specify project_id to disambiguate.`),
1449
+ candidates,
1450
+ },
1451
+ failures: result.failures,
1452
+ bytes: 0,
1453
+ tokensSaved: 0,
1454
+ });
1455
+ }
1456
+ const found = result.rows.find((r) => r.slug === slug);
1457
+ if (!found) {
1458
+ return jsonContent({
1459
+ summary: `Blueprint "${slug}" not found across ${result.projects.length} project(s)`,
1460
+ blueprint: null,
1461
+ next_action: makeNextAction('disambiguate_slug', `No blueprint with slug "${slug}" found. Check the slug or re-ingest.`),
1462
+ failures: result.failures,
1463
+ bytes: 0,
1464
+ tokensSaved: 0,
1465
+ });
1466
+ }
1467
+ // Fetch tasks from the owning project's DB
1468
+ const owningProject = result.projects.find((pr) => pr.project_id === found.project_id);
1469
+ let tasks = [];
1470
+ if (owningProject) {
1471
+ const owningDbPath = dbPath(owningProject.worktree_path);
1472
+ if (existsSync(owningDbPath)) {
1473
+ const conn = openDb(owningDbPath);
1474
+ try {
1475
+ tasks = conn.db
1476
+ .prepare(`SELECT task_id, title, status, wave, lane FROM tasks WHERE blueprint_slug = ? ORDER BY id`)
1477
+ .all(slug);
1478
+ }
1479
+ finally {
1480
+ conn.close();
1481
+ }
1482
+ }
1483
+ }
1484
+ const headAtIngest = owningProject
1485
+ ? (readProjectionMetadata(dbPath(owningProject.worktree_path))?.head_at_ingest ?? null)
1486
+ : null;
1487
+ const blueprintWithTasks = { ...found, tasks };
1488
+ const b = bytes(JSON.stringify(blueprintWithTasks));
1489
+ return jsonContent({
1490
+ summary: `Blueprint "${slug}": ${found.status}, ${tasks.length} task(s) [project: ${found.project_id}]`,
1491
+ blueprint: blueprintWithTasks,
1492
+ content_hash: found.content_hash,
1493
+ ingested_at: found.ingested_at,
1494
+ head_at_ingest: headAtIngest,
1495
+ project_id: found.project_id,
1496
+ failures: result.failures,
1497
+ bytes: b,
1498
+ tokensSaved: 0,
1499
+ });
1500
+ }
1501
+ catch (e) {
1502
+ return err('wp_blueprint_get failed', toStr(e));
1503
+ }
1504
+ }
1505
+ // Single-project path
1506
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
1507
+ if ('content' in resolvedProject)
1508
+ return resolvedProject;
1509
+ const projectCwd = resolvedProject.cwd;
1510
+ await ensureProjectionReady(projectCwd);
1511
+ const target = dbPath(projectCwd);
1512
+ if (!existsSync(target))
1513
+ return jsonContent({
1514
+ summary: 'No blueprint DB found',
1515
+ blueprint: null,
1516
+ next_action: makeNextAction('rebuild_db', 'Blueprint DB missing. Re-ingest to create it.'),
1517
+ failures: [],
1518
+ bytes: 0,
1519
+ tokensSaved: 0,
1520
+ });
1521
+ const getFreshness = checkFreshness({ worktree_path: projectCwd, db_path: target });
1522
+ if (!getFreshness.ok) {
1523
+ return staleProjectionResponse('Blueprint projection is stale', getFreshness.next_action, {
1524
+ blueprint: null,
1525
+ content_hash: null,
1526
+ ingested_at: null,
1527
+ head_at_ingest: null,
1528
+ project_id: resolvedProject.project_id ?? projectCwd,
1529
+ });
1530
+ }
1531
+ try {
1532
+ const conn = openDb(target);
1533
+ let blueprint;
1534
+ let tasks;
1535
+ try {
1536
+ blueprint =
1537
+ conn.db
1538
+ .prepare(`SELECT slug, title, status, complexity, owner, last_updated, content_hash, ingested_at, file_path FROM blueprints WHERE slug = ?`)
1539
+ .get(slug) ?? null;
1540
+ tasks = blueprint
1541
+ ? conn.db
1542
+ .prepare(`SELECT task_id, title, status, wave, lane FROM tasks WHERE blueprint_slug = ? ORDER BY id`)
1543
+ .all(slug)
1544
+ : [];
1545
+ }
1546
+ finally {
1547
+ conn.close();
1548
+ }
1549
+ if (!blueprint) {
1550
+ return jsonContent({
1551
+ summary: `Blueprint "${slug}" not found`,
1552
+ blueprint: null,
1553
+ next_action: makeNextAction('disambiguate_slug', `No blueprint with slug "${slug}" found in the DB. Check the slug or re-ingest.`),
1554
+ failures: [`Blueprint "${slug}" not found`],
1555
+ bytes: 0,
1556
+ tokensSaved: 0,
1557
+ });
1558
+ }
1559
+ const result = { ...blueprint, tasks };
1560
+ const b = bytes(JSON.stringify(result));
1561
+ const headAtIngest = readProjectionMetadata(target)?.head_at_ingest ?? null;
1562
+ return jsonContent({
1563
+ summary: `Blueprint "${slug}": ${blueprint.status}, ${tasks.length} task(s)`,
1564
+ blueprint: result,
1565
+ content_hash: blueprint.content_hash,
1566
+ ingested_at: blueprint.ingested_at,
1567
+ head_at_ingest: headAtIngest,
1568
+ project_id: resolvedProject.project_id ?? projectCwd,
1569
+ failures: [],
1570
+ bytes: b,
1571
+ tokensSaved: 0,
1572
+ });
1573
+ }
1574
+ catch (e) {
1575
+ return err('wp_blueprint_get failed', toStr(e));
1576
+ }
1577
+ }
1578
+ const contextSchema = ReadTarget.extend({
1579
+ slug: z.string(),
1580
+ task_id: z.string().optional(),
1581
+ });
1582
+ async function handleBlueprintContext(projectResolver, cwd, raw) {
1583
+ const p = contextSchema.safeParse(raw);
1584
+ if (!p.success)
1585
+ return err('wp_blueprint_context validation error', p.error.message);
1586
+ const { slug, task_id, project_id } = p.data;
1587
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
1588
+ if ('content' in resolvedProject)
1589
+ return resolvedProject;
1590
+ const projectCwd = resolvedProject.cwd;
1591
+ await ensureProjectionReady(projectCwd);
1592
+ const target = dbPath(projectCwd);
1593
+ if (!existsSync(target))
1594
+ return jsonContent({
1595
+ summary: 'No blueprint DB found',
1596
+ chunks: [],
1597
+ total_bytes: 0,
1598
+ next_action: makeNextAction('rebuild_db', 'Blueprint DB missing. Re-ingest to create it.'),
1599
+ failures: [],
1600
+ bytes: 0,
1601
+ tokensSaved: 0,
1602
+ });
1603
+ const contextFreshness = checkFreshness({ worktree_path: projectCwd, db_path: target });
1604
+ if (!contextFreshness.ok) {
1605
+ return staleProjectionResponse('Blueprint projection is stale', contextFreshness.next_action, {
1606
+ chunks: [],
1607
+ total_bytes: 0,
1608
+ content_hash: null,
1609
+ ingested_at: null,
1610
+ head_at_ingest: null,
1611
+ project_id: resolvedProject.project_id ?? projectCwd,
1612
+ });
1613
+ }
1614
+ try {
1615
+ const conn = openDb(target);
1616
+ let blueprint;
1617
+ let tasks;
1618
+ try {
1619
+ blueprint =
1620
+ conn.db
1621
+ .prepare(`SELECT slug, title, status, complexity, file_path, last_updated, content_hash, ingested_at FROM blueprints WHERE slug = ?`)
1622
+ .get(slug) ?? null;
1623
+ tasks = blueprint
1624
+ ? conn.db
1625
+ .prepare(`SELECT task_id, title, status, description, acceptance_json, wave FROM tasks WHERE blueprint_slug = ? ORDER BY id`)
1626
+ .all(slug)
1627
+ : [];
1628
+ }
1629
+ finally {
1630
+ conn.close();
1631
+ }
1632
+ if (!blueprint) {
1633
+ return jsonContent({
1634
+ summary: `Blueprint "${slug}" not found`,
1635
+ chunks: [],
1636
+ total_bytes: 0,
1637
+ next_action: makeNextAction('disambiguate_slug', `No blueprint with slug "${slug}" found. Check the slug or re-ingest.`),
1638
+ failures: [`Blueprint "${slug}" not found`],
1639
+ bytes: 0,
1640
+ tokensSaved: 0,
1641
+ });
1642
+ }
1643
+ // Assemble context chunks inline to preserve the existing MCP payload shape.
1644
+ const chunks = [];
1645
+ const summaryContent = `# ${blueprint.title}\nStatus: ${blueprint.status}\nComplexity: ${blueprint.complexity ?? 'unset'}\nLast updated: ${blueprint.last_updated ?? 'unknown'}`;
1646
+ chunks.push({
1647
+ kind: 'summary',
1648
+ label: `Blueprint: ${slug}`,
1649
+ content: summaryContent,
1650
+ byte_size: bytes(summaryContent),
1651
+ });
1652
+ const filteredTasks = task_id ? tasks.filter((t) => t.task_id === task_id) : tasks;
1653
+ for (const t of filteredTasks) {
1654
+ const taskContent = `## Task ${t.task_id}: ${t.title}\nStatus: ${t.status}\nWave: ${t.wave ?? 'unset'}\n${t.description ?? ''}`;
1655
+ chunks.push({
1656
+ kind: 'task',
1657
+ label: `Task ${t.task_id}`,
1658
+ content: taskContent,
1659
+ byte_size: bytes(taskContent),
1660
+ });
1661
+ }
1662
+ if (task_id && filteredTasks.length === 0) {
1663
+ return jsonContent({
1664
+ summary: `Task "${task_id}" not found in blueprint "${slug}"`,
1665
+ chunks: [],
1666
+ total_bytes: 0,
1667
+ next_action: makeNextAction('verify_task', `Task "${task_id}" not found. Check the task_id or use wp_blueprint_get to list available tasks.`),
1668
+ failures: [`Task "${task_id}" not found in blueprint "${slug}"`],
1669
+ bytes: 0,
1670
+ tokensSaved: 0,
1671
+ });
1672
+ }
1673
+ const totalBytes = chunks.reduce((acc, c) => acc + c.byte_size, 0);
1674
+ const b = bytes(JSON.stringify(chunks));
1675
+ const headAtIngest = readProjectionMetadata(target)?.head_at_ingest ?? null;
1676
+ return jsonContent({
1677
+ summary: `Context for "${slug}"${task_id ? ` task "${task_id}"` : ''}: ${chunks.length} chunk(s), ${totalBytes} bytes`,
1678
+ chunks,
1679
+ total_bytes: totalBytes,
1680
+ content_hash: blueprint.content_hash,
1681
+ ingested_at: blueprint.ingested_at,
1682
+ head_at_ingest: headAtIngest,
1683
+ project_id: resolvedProject.project_id ?? projectCwd,
1684
+ failures: [],
1685
+ bytes: b,
1686
+ tokensSaved: 0,
1687
+ });
1688
+ }
1689
+ catch (e) {
1690
+ return err('wp_blueprint_context failed', toStr(e));
1691
+ }
1692
+ }
1693
+ const createSchema = MutationTarget.extend({
1694
+ title: z.string(),
1695
+ goal: z.string(),
1696
+ complexity: z.enum(['XS', 'S', 'M', 'L', 'XL']).default('M'),
1697
+ tags: z.array(z.string()).optional(),
1698
+ request_id: z.string().min(1).optional(),
1699
+ head_at_ingest: z.string().nullable().optional(),
1700
+ });
1701
+ async function handleBlueprintCreate(projectResolver, cwd, raw) {
1702
+ const p = createSchema.safeParse(raw);
1703
+ if (!p.success)
1704
+ return err('wp_blueprint_create validation error', p.error.message);
1705
+ const { project_id, title, goal, complexity, tags, request_id, head_at_ingest } = p.data;
1706
+ const resolvedProject = await resolveToolProject(projectResolver, cwd, project_id);
1707
+ if ('content' in resolvedProject)
1708
+ return resolvedProject;
1709
+ const projectCwd = resolvedProject.cwd;
1710
+ await ensureProjectionReady(projectCwd);
1711
+ const freshnessFailure = validateMutationFreshnessToken(projectCwd, head_at_ingest, 'wp_blueprint_create', 'wp_blueprint_list');
1712
+ if (freshnessFailure)
1713
+ return freshnessFailure;
1714
+ const payloadHash = hashMutationPayload({ title, goal, complexity, tags: tags ?? [] });
1715
+ const replay = request_id !== undefined
1716
+ ? readMutationReplay(projectCwd, 'wp_blueprint_create', request_id, payloadHash)
1717
+ : null;
1718
+ if (replay)
1719
+ return replay;
1720
+ const today = new Date().toISOString().split('T')[0] ?? '';
1721
+ const slug = titleToSlug(title);
1722
+ const root = resolveBlueprintRoot(projectCwd);
1723
+ const targetDir = path.join(root, 'draft', slug);
1724
+ const overviewPath = path.join(targetDir, '_overview.md');
1725
+ try {
1726
+ mkdirSync(targetDir, { recursive: true });
1727
+ const content = BLUEPRINT_TEMPLATE.replace(/{TITLE}/g, title)
1728
+ .replace(/{COMPLEXITY}/g, complexity)
1729
+ .replace(/{DATE}/g, today)
1730
+ .replace('{GOAL}', goal);
1731
+ writeFileSync(overviewPath, content, 'utf8');
1732
+ // Re-ingest so the DB reflects the new blueprint
1733
+ await reIngest(projectCwd);
1734
+ const b = bytes(content);
1735
+ const payload = {
1736
+ summary: `Blueprint "${slug}" created at ${overviewPath}`,
1737
+ slug,
1738
+ path: overviewPath,
1739
+ idempotent: false,
1740
+ next_action: makeNextAction('verify_task', 'Blueprint created. Next: run wp_blueprint_validate to check structure, then /plan-refine to harden, /plan-eng-review to validate architecture.'),
1741
+ failures: [],
1742
+ bytes: b,
1743
+ tokensSaved: 0,
1744
+ };
1745
+ if (request_id !== undefined) {
1746
+ recordMutationReplay(projectCwd, 'wp_blueprint_create', request_id, payloadHash, payload);
1747
+ }
1748
+ return finishPayload(payload);
1749
+ }
1750
+ catch (e) {
1751
+ return err('wp_blueprint_create failed', toStr(e));
1752
+ }
1753
+ }
1754
+ // ---------------------------------------------------------------------------
1755
+ // Registration
1756
+ // ---------------------------------------------------------------------------
1757
+ const nextActionOutputSchema = {
1758
+ type: 'object',
1759
+ properties: {
1760
+ kind: { type: 'string' },
1761
+ hint: { type: 'string' },
1762
+ },
1763
+ required: ['kind', 'hint'],
1764
+ };
1765
+ const summaryEnvelopeOutputSchema = {
1766
+ type: 'object',
1767
+ properties: {
1768
+ summary: { type: 'string' },
1769
+ failures: { type: 'array', items: { type: 'string' } },
1770
+ bytes: { type: 'number' },
1771
+ tokensSaved: { type: 'number' },
1772
+ },
1773
+ required: ['summary', 'failures', 'bytes', 'tokensSaved'],
1774
+ };
1775
+ export async function registerBlueprintTools(registrar, cwd, projectResolver = createProjectResolver()) {
1776
+ registrar.registerTool('wp_blueprint_query', 'Run a pre-registered SQL template against the blueprint store. Returns { summary, rows_capped, rows, failures, bytes, tokensSaved }.', {
1777
+ type: 'object',
1778
+ properties: { template_id: { type: 'string' }, params: { type: 'object', default: {} } },
1779
+ required: ['template_id'],
1780
+ }, undefined, (r) => handleQuery(cwd, r), { title: 'Blueprint Query', readOnlyHint: true, openWorldHint: false });
1781
+ registrar.registerTool('wp_blueprint_new', 'Return a drafting bundle for a new blueprint (no LLM call). Returns { target_path, template, rules_context, examples, lifecycle_advice, validation_required }.', {
1782
+ type: 'object',
1783
+ properties: {
1784
+ title: { type: 'string' },
1785
+ complexity: { type: 'string', enum: ['XS', 'S', 'M', 'L', 'XL'], default: 'M' },
1786
+ goal_prompt: { type: 'string' },
1787
+ examples_count: { type: 'integer', minimum: 0, maximum: 5, default: 3 },
1788
+ },
1789
+ required: ['title', 'goal_prompt'],
1790
+ }, undefined, (r) => handleNew(cwd, r), { title: 'Blueprint New', readOnlyHint: true, openWorldHint: false });
1791
+ registrar.registerTool('wp_blueprint_validate', 'Validate _overview.md structure. Returns { valid, gaps }. Must pass before wp_blueprint_promote.', { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] }, undefined, (r) => handleValidate(cwd, r), { title: 'Blueprint Validate', readOnlyHint: false, openWorldHint: false });
1792
+ registrar.registerTool('wp_blueprint_task_next', 'Return the next ready task (all deps done). Accepts optional project_id for nested-workspace disambiguation. Returns { summary, task }.', {
1793
+ type: 'object',
1794
+ properties: { blueprint: { type: 'string' }, project_id: { type: 'string' } },
1795
+ }, undefined, (r) => handleTaskNext(projectResolver, cwd, r), { title: 'Blueprint Task Next', readOnlyHint: true, openWorldHint: false });
1796
+ registrar.registerTool('wp_blueprint_task_advance', 'Advance task status. Edits _overview.md and re-syncs DB. Accepts optional request_id for idempotent retries and optional head_at_ingest from wp_blueprint_get/wp_blueprint_list to reject stale writes. Returns { summary, old_status, new_status, idempotent }.', {
1797
+ type: 'object',
1798
+ properties: {
1799
+ project_id: { type: 'string' },
1800
+ task_id: { type: 'string' },
1801
+ to: { type: 'string', enum: ['todo', 'in-progress', 'blocked', 'done', 'dropped'] },
1802
+ request_id: { type: 'string' },
1803
+ head_at_ingest: { type: ['string', 'null'] },
1804
+ },
1805
+ required: ['project_id', 'task_id', 'to'],
1806
+ }, {
1807
+ ...summaryEnvelopeOutputSchema,
1808
+ properties: {
1809
+ ...summaryEnvelopeOutputSchema.properties,
1810
+ task_id: { type: 'string' },
1811
+ old_status: { type: ['string', 'null'] },
1812
+ new_status: { type: 'string' },
1813
+ idempotent: { type: 'boolean' },
1814
+ next_action: nextActionOutputSchema,
1815
+ },
1816
+ }, (r) => handleTaskAdvance(projectResolver, cwd, r), { title: 'Blueprint Task Advance', destructiveHint: false, openWorldHint: false });
1817
+ registrar.registerTool('wp_blueprint_promote', 'Promote a blueprint to a new lifecycle state. Refuses without prior validate. Returns { summary, new_path }.', {
1818
+ type: 'object',
1819
+ properties: {
1820
+ project_id: { type: 'string' },
1821
+ slug: { type: 'string' },
1822
+ to_state: {
1823
+ type: 'string',
1824
+ enum: ['planned', 'in-progress', 'completed', 'parked', 'archived'],
1825
+ },
1826
+ },
1827
+ required: ['slug', 'to_state'],
1828
+ }, undefined, (r) => handlePromote(projectResolver, cwd, r), { title: 'Blueprint Promote', destructiveHint: false, openWorldHint: false });
1829
+ registrar.registerTool('wp_blueprint_finalize', 'Finalize a blueprint (move to completed). Accepts optional project_id for nested-workspace disambiguation. Refuses if any tasks are not done/dropped. Returns { summary, new_path }.', {
1830
+ type: 'object',
1831
+ properties: { project_id: { type: 'string' }, slug: { type: 'string' } },
1832
+ required: ['slug'],
1833
+ }, undefined, (r) => handleFinalize(projectResolver, cwd, r), { title: 'Blueprint Finalize', destructiveHint: false, openWorldHint: false });
1834
+ registrar.registerTool('wp_blueprint_depgraph', 'Build dependency graph from a blueprint slug. Private cross-org targets shown as private/<hash>. Returns { summary, nodes, edges }.', { type: 'object', properties: { from: { type: 'string' } }, required: ['from'] }, undefined, (r) => handleDepgraph(cwd, r), { title: 'Blueprint Dep Graph', readOnlyHint: true, openWorldHint: false });
1835
+ registrar.registerTool('wp_blueprint_list', 'List blueprints in a project from the SQLite projection. Supports optional status filter. Returns { blueprints, project_id, freshness_ok, next_action? }.', {
1836
+ type: 'object',
1837
+ properties: {
1838
+ project_id: { type: 'string' },
1839
+ scope: { type: 'string', enum: ['current', 'roots', 'workspace', 'all'] },
1840
+ status: {
1841
+ type: 'string',
1842
+ enum: ['draft', 'planned', 'in-progress', 'completed', 'parked', 'archived'],
1843
+ },
1844
+ limit: { type: 'integer', minimum: 1, maximum: 500, default: 100 },
1845
+ },
1846
+ required: [],
1847
+ }, {
1848
+ ...summaryEnvelopeOutputSchema,
1849
+ properties: {
1850
+ ...summaryEnvelopeOutputSchema.properties,
1851
+ blueprints: { type: 'array', items: { type: 'object' } },
1852
+ project_id: { type: 'string' },
1853
+ freshness_ok: { type: 'boolean' },
1854
+ next_action: nextActionOutputSchema,
1855
+ },
1856
+ required: [
1857
+ ...summaryEnvelopeOutputSchema.required,
1858
+ 'blueprints',
1859
+ 'project_id',
1860
+ 'freshness_ok',
1861
+ ],
1862
+ }, (r) => handleBlueprintList(projectResolver, cwd, r), { title: 'Blueprint List', readOnlyHint: true, openWorldHint: false });
1863
+ registrar.registerTool('wp_blueprint_get', 'Get a single blueprint by slug with task list and freshness metadata. Returns { blueprint, content_hash, ingested_at, next_action? }.', {
1864
+ type: 'object',
1865
+ properties: {
1866
+ slug: { type: 'string' },
1867
+ project_id: { type: 'string' },
1868
+ scope: { type: 'string', enum: ['current', 'roots', 'workspace', 'all'] },
1869
+ },
1870
+ required: ['slug'],
1871
+ }, {
1872
+ ...summaryEnvelopeOutputSchema,
1873
+ properties: {
1874
+ ...summaryEnvelopeOutputSchema.properties,
1875
+ blueprint: { type: ['object', 'null'] },
1876
+ content_hash: { type: ['string', 'null'] },
1877
+ ingested_at: { type: ['number', 'null'] },
1878
+ head_at_ingest: { type: ['string', 'null'] },
1879
+ project_id: { type: 'string' },
1880
+ next_action: nextActionOutputSchema,
1881
+ },
1882
+ required: [
1883
+ ...summaryEnvelopeOutputSchema.required,
1884
+ 'blueprint',
1885
+ 'content_hash',
1886
+ 'ingested_at',
1887
+ 'head_at_ingest',
1888
+ 'project_id',
1889
+ ],
1890
+ }, (r) => handleBlueprintGet(projectResolver, cwd, r), { title: 'Blueprint Get', readOnlyHint: true, openWorldHint: false });
1891
+ registrar.registerTool('wp_blueprint_context', 'Assemble context chunks for a blueprint (and optionally a specific task). Returns { chunks, total_bytes, next_action? }.', {
1892
+ type: 'object',
1893
+ properties: {
1894
+ slug: { type: 'string' },
1895
+ task_id: { type: 'string' },
1896
+ project_id: { type: 'string' },
1897
+ scope: { type: 'string', enum: ['current', 'roots', 'workspace', 'all'] },
1898
+ },
1899
+ required: ['slug'],
1900
+ }, {
1901
+ ...summaryEnvelopeOutputSchema,
1902
+ properties: {
1903
+ ...summaryEnvelopeOutputSchema.properties,
1904
+ chunks: { type: 'array', items: { type: 'object' } },
1905
+ total_bytes: { type: 'number' },
1906
+ content_hash: { type: ['string', 'null'] },
1907
+ ingested_at: { type: ['number', 'null'] },
1908
+ head_at_ingest: { type: ['string', 'null'] },
1909
+ project_id: { type: 'string' },
1910
+ next_action: nextActionOutputSchema,
1911
+ },
1912
+ required: [...summaryEnvelopeOutputSchema.required, 'chunks', 'total_bytes', 'project_id'],
1913
+ }, (r) => handleBlueprintContext(projectResolver, cwd, r), { title: 'Blueprint Context', readOnlyHint: true, openWorldHint: false });
1914
+ registrar.registerTool('wp_blueprint_create', 'Create a new blueprint markdown under blueprints/draft/<slug>/_overview.md and re-ingest. Accepts optional request_id for idempotent retries and optional head_at_ingest from wp_blueprint_projects/wp_blueprint_list to reject stale writes. Returns { slug, path, next_action, idempotent }.', {
1915
+ type: 'object',
1916
+ properties: {
1917
+ project_id: { type: 'string' },
1918
+ title: { type: 'string' },
1919
+ goal: { type: 'string' },
1920
+ complexity: { type: 'string', enum: ['XS', 'S', 'M', 'L', 'XL'], default: 'M' },
1921
+ tags: { type: 'array', items: { type: 'string' } },
1922
+ request_id: { type: 'string' },
1923
+ head_at_ingest: { type: ['string', 'null'] },
1924
+ },
1925
+ required: ['project_id', 'title', 'goal'],
1926
+ }, {
1927
+ ...summaryEnvelopeOutputSchema,
1928
+ properties: {
1929
+ ...summaryEnvelopeOutputSchema.properties,
1930
+ slug: { type: 'string' },
1931
+ path: { type: 'string' },
1932
+ idempotent: { type: 'boolean' },
1933
+ next_action: nextActionOutputSchema,
1934
+ },
1935
+ required: [
1936
+ ...summaryEnvelopeOutputSchema.required,
1937
+ 'slug',
1938
+ 'path',
1939
+ 'idempotent',
1940
+ 'next_action',
1941
+ ],
1942
+ }, (r) => handleBlueprintCreate(projectResolver, cwd, r), { title: 'Blueprint Create', destructiveHint: false, openWorldHint: false });
1943
+ registrar.registerTool('wp_blueprint_task_verify', 'Mark a task done with an Evidence Contract. Requires at least one pass evidence item. Accepts optional request_id for idempotent retries, optional head_at_ingest from wp_blueprint_get/wp_blueprint_context to reject stale writes, and re-ingests DB on success. Returns { status, idempotent, next_action? }.', {
1944
+ type: 'object',
1945
+ properties: {
1946
+ project_id: { type: 'string' },
1947
+ slug: { type: 'string' },
1948
+ task_id: { type: 'string' },
1949
+ request_id: { type: 'string' },
1950
+ head_at_ingest: { type: ['string', 'null'] },
1951
+ evidence: {
1952
+ type: 'array',
1953
+ minItems: 1,
1954
+ items: {
1955
+ type: 'object',
1956
+ properties: {
1957
+ kind: { type: 'string', enum: ['test', 'integration', 'audit', 'manual'] },
1958
+ result: { type: 'string', enum: ['pass', 'fail'] },
1959
+ ts: { type: 'string' },
1960
+ },
1961
+ required: ['kind', 'result', 'ts'],
1962
+ },
1963
+ },
1964
+ },
1965
+ required: ['project_id', 'slug', 'task_id', 'evidence'],
1966
+ }, {
1967
+ ...summaryEnvelopeOutputSchema,
1968
+ properties: {
1969
+ ...summaryEnvelopeOutputSchema.properties,
1970
+ status: { type: 'string' },
1971
+ idempotent: { type: 'boolean' },
1972
+ next_summary: { type: 'string' },
1973
+ next_task: { type: ['object', 'null'] },
1974
+ next_action: nextActionOutputSchema,
1975
+ },
1976
+ }, (r) => handleTaskVerify(projectResolver, cwd, r), { title: 'Blueprint Task Verify', destructiveHint: false, openWorldHint: false });
1977
+ }
1978
+ const BLUEPRINT_SURFACE_TOOLS = [
1979
+ 'wp_blueprint_query',
1980
+ 'wp_blueprint_new',
1981
+ 'wp_blueprint_validate',
1982
+ 'wp_blueprint_task_next',
1983
+ 'wp_blueprint_task_advance',
1984
+ 'wp_blueprint_promote',
1985
+ 'wp_blueprint_finalize',
1986
+ 'wp_blueprint_depgraph',
1987
+ 'wp_blueprint_projects',
1988
+ ];
1989
+ /**
1990
+ * Wire the blueprint structured-store tools into the main MCP server.
1991
+ *
1992
+ * Single integration point (F13/E15): call this once from `createServer` AFTER
1993
+ * `auto-discover` finishes so tool-name collisions surface as a registration
1994
+ * error rather than silent shadow. Adds `wp_blueprint_projects` on top of the
1995
+ * 8 existing tools.
1996
+ *
1997
+ * Roots handling (F5):
1998
+ * - Roots are looked up lazily via `getMcpRoots` (callers pass a thunk that
1999
+ * calls `server.listRoots()`). If the client does not support roots, the
2000
+ * callback throws `assertClientCapability` — that throw is caught here, the
2001
+ * tool result includes an `unsupported_roots` warning, and the current
2002
+ * project still resolves from cwd.
2003
+ * - `onRootsListChanged` lets the caller hook a notification handler so the
2004
+ * cached roots invalidate on the next read.
2005
+ */
2006
+ export async function registerBlueprintServer(registrar, options) {
2007
+ const cwd = options.cwd ?? process.cwd();
2008
+ const projectResolver = options.projectResolver ?? createProjectResolver();
2009
+ // F13/E15: hard-fail on collision before doing any work — silent shadowing
2010
+ // would hide the conflict until a downstream tool-call surfaced it.
2011
+ for (const name of BLUEPRINT_SURFACE_TOOLS) {
2012
+ if (options.existingToolNames.has(name)) {
2013
+ throw new Error(`[blueprint-server] tool name "${name}" collides with an auto-discovered tool; rename one of them before registering`);
2014
+ }
2015
+ }
2016
+ // Register the 8 existing structured-store tools.
2017
+ await registerBlueprintTools(registrar, cwd, projectResolver);
2018
+ const cache = { fetched: false, roots: [], unsupported: false, timedOut: false };
2019
+ async function ensureRoots() {
2020
+ if (cache.fetched)
2021
+ return cache;
2022
+ if (!options.getMcpRoots) {
2023
+ cache.fetched = true;
2024
+ cache.roots = [];
2025
+ cache.unsupported = false;
2026
+ cache.timedOut = false;
2027
+ return cache;
2028
+ }
2029
+ try {
2030
+ const timed = await awaitBounded(options.getMcpRoots(), readBoundedTimeoutMs('WP_BLUEPRINT_ROOTS_TIMEOUT_MS', DEFAULT_ROOTS_FETCH_TIMEOUT_MS));
2031
+ if (timed.timedOut) {
2032
+ cache.fetched = true;
2033
+ cache.roots = [];
2034
+ cache.unsupported = false;
2035
+ cache.timedOut = true;
2036
+ return cache;
2037
+ }
2038
+ cache.fetched = true;
2039
+ cache.roots = timed.value.roots;
2040
+ cache.unsupported = false;
2041
+ cache.timedOut = false;
2042
+ }
2043
+ catch {
2044
+ // Roots capability missing on the client — degrade gracefully.
2045
+ cache.fetched = true;
2046
+ cache.roots = [];
2047
+ cache.unsupported = true;
2048
+ cache.timedOut = false;
2049
+ }
2050
+ return cache;
2051
+ }
2052
+ if (options.onRootsListChanged) {
2053
+ options.onRootsListChanged(() => {
2054
+ cache.fetched = false;
2055
+ cache.roots = [];
2056
+ cache.unsupported = false;
2057
+ cache.timedOut = false;
2058
+ });
2059
+ }
2060
+ registrar.registerTool('wp_blueprint_projects', 'List blueprint-bearing projects from current cwd, MCP roots, workspace config, and git worktrees. Returns { summary, projects, warnings, next_action? }.', {
2061
+ type: 'object',
2062
+ properties: {
2063
+ scope: {
2064
+ type: 'string',
2065
+ enum: ['current', 'roots', 'workspace', 'all'],
2066
+ default: 'all',
2067
+ },
2068
+ },
2069
+ }, {
2070
+ ...summaryEnvelopeOutputSchema,
2071
+ properties: {
2072
+ ...summaryEnvelopeOutputSchema.properties,
2073
+ projects: { type: 'array', items: { type: 'object' } },
2074
+ warnings: { type: 'array', items: { type: 'string' } },
2075
+ next_action: nextActionOutputSchema,
2076
+ },
2077
+ required: [...summaryEnvelopeOutputSchema.required, 'projects', 'warnings'],
2078
+ }, async (input) => handleProjects(projectResolver, cwd, ensureRoots, input), { title: 'Blueprint Projects', readOnlyHint: true, openWorldHint: false });
2079
+ }
2080
+ async function handleProjects(projectResolver, cwd, ensureRoots, raw) {
2081
+ const scopeSchema = z.object({
2082
+ scope: z.enum(['current', 'roots', 'workspace', 'all']).optional(),
2083
+ });
2084
+ const parsed = scopeSchema.safeParse(raw);
2085
+ const rootsState = await ensureRoots();
2086
+ const timedProjects = await awaitBounded(projectResolver.listVisibleProjects({
2087
+ cwd,
2088
+ rootsProvider: rootsState.roots.length > 0 ? async () => ({ roots: rootsState.roots }) : undefined,
2089
+ }), readBoundedTimeoutMs('WP_BLUEPRINT_PROJECT_DISCOVERY_TIMEOUT_MS', DEFAULT_PROJECT_DISCOVERY_TIMEOUT_MS));
2090
+ const projects = timedProjects.timedOut ? [buildFallbackCurrentProject(cwd)] : timedProjects.value;
2091
+ const scope = parsed.success ? (parsed.data.scope ?? 'all') : 'all';
2092
+ const filteredProjects = projects.filter((project) => {
2093
+ if (scope === 'all')
2094
+ return true;
2095
+ if (scope === 'current') {
2096
+ return (project.source === PROJECT_SOURCES.current ||
2097
+ project.source === PROJECT_SOURCES.recursive_scan);
2098
+ }
2099
+ if (scope === 'roots')
2100
+ return project.source === PROJECT_SOURCES.mcp_roots;
2101
+ return (project.source === PROJECT_SOURCES.workspace_config ||
2102
+ project.source === PROJECT_SOURCES.git_worktree);
2103
+ });
2104
+ const warnings = [];
2105
+ if (rootsState.unsupported)
2106
+ warnings.push('unsupported_roots');
2107
+ if (rootsState.timedOut)
2108
+ warnings.push('roots_fetch_timeout');
2109
+ if (timedProjects.timedOut)
2110
+ warnings.push('project_discovery_timeout');
2111
+ const summary = filteredProjects.length === 0
2112
+ ? 'No blueprint-bearing projects found'
2113
+ : timedProjects.timedOut
2114
+ ? `Project discovery timed out; returning ${filteredProjects.length} current-project result${filteredProjects.length === 1 ? '' : 's'}`
2115
+ : `Found ${filteredProjects.length} project${filteredProjects.length === 1 ? '' : 's'}`;
2116
+ const payload = {
2117
+ summary,
2118
+ projects: filteredProjects,
2119
+ warnings,
2120
+ };
2121
+ if (!timedProjects.timedOut)
2122
+ projectResolver.warm(projects);
2123
+ if (rootsState.unsupported) {
2124
+ payload.next_action = makeNextAction('unsupported_roots', 'MCP client does not advertise the roots capability; only the current cwd was scanned. Pass --roots explicitly or configure workspace.yaml.');
2125
+ }
2126
+ return {
2127
+ content: [{ type: 'text', text: JSON.stringify(payload) }],
2128
+ structuredContent: payload,
2129
+ };
2130
+ }
2131
+ //# sourceMappingURL=blueprint-server.js.map