@sureshdsk/devflow-mcp 3.0.0 → 3.0.1

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 (504) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +4 -4
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  6. package/.next/standalone/.next/server/app/_global-error/page.js +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  16. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  17. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.rsc +14 -13
  21. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -13
  22. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +5 -4
  24. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  27. package/.next/standalone/.next/server/app/api/projects/[id]/route.js +2 -2
  28. package/.next/standalone/.next/server/app/api/projects/[id]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/projects/route.js +2 -2
  30. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/approve/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/approve/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/route.js +2 -2
  34. package/.next/standalone/.next/server/app/api/specs/[name]/artifacts/[artifactType]/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/specs/[name]/promote/route.js +2 -2
  36. package/.next/standalone/.next/server/app/api/specs/[name]/promote/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/specs/[name]/route.js +2 -2
  38. package/.next/standalone/.next/server/app/api/specs/[name]/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/specs/route.js +2 -2
  40. package/.next/standalone/.next/server/app/api/specs/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/tasks/[id]/route.js +2 -2
  42. package/.next/standalone/.next/server/app/api/tasks/[id]/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/tasks/route.js +2 -2
  44. package/.next/standalone/.next/server/app/api/tasks/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/index.html +1 -1
  46. package/.next/standalone/.next/server/app/index.rsc +15 -14
  47. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  48. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -14
  49. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  50. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +5 -4
  51. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  52. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  53. package/.next/standalone/.next/server/app/page.js +2 -2
  54. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/specs/[name]/page/build-manifest.json +2 -2
  57. package/.next/standalone/.next/server/app/specs/[name]/page.js +2 -2
  58. package/.next/standalone/.next/server/app/specs/[name]/page.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/specs/[name]/page_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0be0eb8b._.js +3 -0
  61. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__a9d478ee._.js → [root-of-the-server]__160c54ca._.js} +2 -2
  62. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17ac51e3._.js +3 -0
  63. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bb083e9._.js +3 -0
  64. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1dc1e944._.js +3 -0
  65. package/.next/standalone/.next/server/chunks/[root-of-the-server]__22ecfa2c._.js +3 -0
  66. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__13a93eb6._.js → [root-of-the-server]__64710c0d._.js} +2 -2
  67. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a2b7e5f2._.js +3 -0
  68. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cf302bda._.js +3 -0
  69. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d85482cd._.js +3 -0
  70. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dfa21757._.js +3 -0
  71. package/.next/standalone/.next/server/chunks/_3f452afe._.js +2 -2
  72. package/.next/standalone/.next/server/chunks/src_db_index_ts_a71f50f0._.js +3 -0
  73. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__023e2c69._.js +3 -0
  74. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0a1a1435._.js +3 -0
  75. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0c49a387._.js +3 -0
  76. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1be1fc5f._.js +3 -0
  77. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3a2f2efb._.js +3 -0
  78. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4693399c._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__937c9212._.js → [root-of-the-server]__72a14301._.js} +2 -2
  80. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8064ca06._.js +3 -0
  81. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8b786d48._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8c052461._.js +3 -0
  83. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8d306066._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__9532fd59._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a119dd75._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__7fb6ef14._.js → [root-of-the-server]__a57b312b._.js} +2 -2
  87. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a80bd0ea._.js +3 -0
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__abe095b3._.js +3 -0
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__ad3bd783._.js +3 -0
  90. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1e05fe0e._.js → [root-of-the-server]__ae9f05d6._.js} +2 -2
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__c8781469._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__c8a25070._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e8c1e595._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/ssr/_0ff3de19._.js +1 -1
  95. package/.next/standalone/.next/server/chunks/ssr/node_modules_01a5cd4b._.js +3 -0
  96. package/.next/standalone/.next/server/chunks/ssr/node_modules_05c6819f._.js +31 -0
  97. package/.next/standalone/.next/server/chunks/ssr/node_modules_06c2c30a._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/ssr/node_modules_09efe605._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/ssr/{node_modules_mermaid_dist_chunks_mermaid_core_ef601841._.js → node_modules_0a439e3b._.js} +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/{node_modules_3507b41a._.js → node_modules_0e73ad6c._.js} +3 -3
  101. package/.next/standalone/.next/server/chunks/ssr/node_modules_0e7ff06d._.js +3 -0
  102. package/.next/standalone/.next/server/chunks/ssr/node_modules_0f73e25c._.js +3 -0
  103. package/.next/standalone/.next/server/chunks/ssr/node_modules_14cf9cea._.js +3 -0
  104. package/.next/standalone/.next/server/chunks/ssr/node_modules_19801f01._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/ssr/node_modules_2235b8cf._.js +17 -0
  106. package/.next/standalone/.next/server/chunks/ssr/node_modules_23096c6d._.js +3 -0
  107. package/.next/standalone/.next/server/chunks/ssr/node_modules_23db4cf7._.js +17 -0
  108. package/.next/standalone/.next/server/chunks/ssr/node_modules_24381e95._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/ssr/node_modules_24ca0eb6._.js +17 -0
  110. package/.next/standalone/.next/server/chunks/ssr/node_modules_27525793._.js +17 -0
  111. package/.next/standalone/.next/server/chunks/ssr/{node_modules_mermaid_dist_chunks_mermaid_core_4cfa6360._.js → node_modules_27c20382._.js} +2 -2
  112. package/.next/standalone/.next/server/chunks/ssr/node_modules_2c901b92._.js +3 -0
  113. package/.next/standalone/.next/server/chunks/ssr/node_modules_33b818b7._.js +45 -0
  114. package/.next/standalone/.next/server/chunks/ssr/node_modules_345d7791._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/node_modules_36185c24._.js +45 -0
  116. package/.next/standalone/.next/server/chunks/ssr/node_modules_3ac7ce09._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/node_modules_41b77cc7._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/{node_modules_ed317ff6._.js → node_modules_42acd8db._.js} +2 -2
  119. package/.next/standalone/.next/server/chunks/ssr/node_modules_434aa5ec._.js +3 -0
  120. package/.next/standalone/.next/server/chunks/ssr/node_modules_54a9e72d._.js +17 -0
  121. package/.next/standalone/.next/server/chunks/ssr/node_modules_54f1273a._.js +26 -0
  122. package/.next/standalone/.next/server/chunks/ssr/node_modules_58d64491._.js +3 -0
  123. package/.next/standalone/.next/server/chunks/ssr/node_modules_5e012e3d._.js +3 -0
  124. package/.next/standalone/.next/server/chunks/ssr/node_modules_5ea9e4cf._.js +3 -0
  125. package/.next/standalone/.next/server/chunks/ssr/node_modules_5ecf8270._.js +26 -0
  126. package/.next/standalone/.next/server/chunks/ssr/node_modules_611c99b5._.js +1 -1
  127. package/.next/standalone/.next/server/chunks/ssr/{node_modules_d3-scale_src_e02ef77f._.js → node_modules_6629853d._.js} +2 -2
  128. package/.next/standalone/.next/server/chunks/ssr/node_modules_6fe2661c._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/node_modules_7fe65a84._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/node_modules_860f971a._.js +3 -0
  131. package/.next/standalone/.next/server/chunks/ssr/node_modules_882f3743._.js +3 -0
  132. package/.next/standalone/.next/server/chunks/ssr/node_modules_8e047938._.js +3 -0
  133. package/.next/standalone/.next/server/chunks/ssr/node_modules_9268cdc4._.js +3 -0
  134. package/.next/standalone/.next/server/chunks/ssr/node_modules_942541c9._.js +3 -0
  135. package/.next/standalone/.next/server/chunks/ssr/node_modules_9d52c0d6._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/node_modules_@tanstack_query-core_build_modern_21ece5ea._.js +3 -0
  137. package/.next/standalone/.next/server/chunks/ssr/node_modules_ae6841d2._.js +17 -0
  138. package/.next/standalone/.next/server/chunks/ssr/node_modules_ba280bb0._.js +31 -0
  139. package/.next/standalone/.next/server/chunks/ssr/node_modules_bffdb8ec._.js +3 -0
  140. package/.next/standalone/.next/server/chunks/ssr/node_modules_c00f1821._.js +17 -0
  141. package/.next/standalone/.next/server/chunks/ssr/node_modules_c142ba86._.js +3 -0
  142. package/.next/standalone/.next/server/chunks/ssr/node_modules_d1a47cde._.js +17 -0
  143. package/.next/standalone/.next/server/chunks/ssr/node_modules_d9b454fe._.js +3 -0
  144. package/.next/standalone/.next/server/chunks/ssr/node_modules_dbe36b1d._.js +3 -0
  145. package/.next/standalone/.next/server/chunks/ssr/node_modules_ddbe26b7._.js +3 -0
  146. package/.next/standalone/.next/server/chunks/ssr/node_modules_e76b8bf2._.js +3 -0
  147. package/.next/standalone/.next/server/chunks/ssr/node_modules_e945b74d._.js +3 -0
  148. package/.next/standalone/.next/server/chunks/ssr/node_modules_fbd8a2ee._.js +17 -0
  149. package/.next/standalone/.next/server/chunks/ssr/node_modules_katex_dist_katex_mjs_31d456ba._.js +3 -0
  150. package/.next/standalone/.next/server/chunks/ssr/node_modules_katex_dist_katex_mjs_e1edc676._.js +3 -0
  151. package/.next/standalone/.next/server/chunks/ssr/node_modules_lodash-es_33e24dce._.js +3 -0
  152. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-QXUST7PY_mjs_159fba97._.js +1 -1
  153. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-S3R3BYOJ_mjs_dbeeb277._.js +1 -1
  154. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_mermaid_core_mjs_a11916de._.js +9 -0
  155. package/.next/standalone/.next/server/chunks/ssr/src_66a70595._.js +3 -0
  156. package/.next/standalone/.next/server/chunks/ssr/src_components_kanban-board_tsx_7b875e8e._.js +1 -1
  157. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  158. package/.next/standalone/.next/server/pages/404.html +1 -1
  159. package/.next/standalone/.next/server/pages/500.html +2 -2
  160. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  162. package/.next/standalone/AGENTS.md +13 -7
  163. package/.next/standalone/CONTRIBUTING.md +42 -26
  164. package/.next/standalone/README.md +166 -25
  165. package/.next/standalone/bin/devflow.js +12 -5
  166. package/.next/standalone/bun.lock +78 -24
  167. package/.next/standalone/devflow/project-config.json +4 -0
  168. package/.next/standalone/devflow/schemas/api-first/schema.yaml +39 -0
  169. package/.next/standalone/devflow/schemas/api-first/templates/api-design.md +41 -0
  170. package/.next/standalone/devflow/schemas/api-first/templates/db-design.md +28 -0
  171. package/.next/standalone/devflow/schemas/api-first/templates/final-architecture.md +31 -0
  172. package/.next/standalone/devflow/schemas/api-first/templates/proposal.md +22 -0
  173. package/.next/standalone/devflow/schemas/api-first/templates/tasks.md +16 -0
  174. package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/.approvals.json +1 -1
  175. package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/.meta.json +1 -1
  176. package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/design.md +11 -0
  177. package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/proposal.md +3 -0
  178. package/.next/standalone/devflow/specs/autodetect-skill-and-slash-command-installation/tasks.md +34 -2
  179. package/.next/standalone/devflow/specs/precommit/.approvals.json +26 -0
  180. package/.next/standalone/devflow/specs/precommit/.meta.json +7 -0
  181. package/.next/standalone/devflow/specs/precommit/design.md +105 -0
  182. package/.next/standalone/devflow/specs/precommit/proposal.md +43 -0
  183. package/.next/standalone/devflow/specs/precommit/specs.md +89 -0
  184. package/.next/standalone/devflow/specs/precommit/tasks.md +283 -0
  185. package/.next/standalone/docs/custom-schemas.md +117 -0
  186. package/.next/standalone/docs/local-dev-guide.md +73 -0
  187. package/.next/standalone/drizzle.config.ts +7 -7
  188. package/.next/standalone/eslint.config.mjs +2 -2
  189. package/.next/standalone/instrumentation.ts +3 -5
  190. package/.next/standalone/next.config.ts +11 -2
  191. package/.next/standalone/node_modules/{sharp → libsql}/node_modules/detect-libc/package.json +4 -8
  192. package/.next/standalone/package-lock.json +5257 -2085
  193. package/.next/standalone/package.json +16 -7
  194. package/.next/standalone/postcss.config.mjs +1 -1
  195. package/.next/standalone/scripts/init-db.js +3 -5
  196. package/.next/standalone/scripts/init-db.test.js +6 -6
  197. package/.next/standalone/scripts/init-schema.js +22 -22
  198. package/.next/standalone/scripts/init-schema.test.js +45 -45
  199. package/.next/standalone/scripts/install-environments.js +27 -8
  200. package/.next/standalone/scripts/install-environments.test.js +19 -10
  201. package/.next/standalone/scripts/install-skills.js +104 -31
  202. package/.next/standalone/scripts/install-skills.test.js +6 -6
  203. package/.next/standalone/server.js +1 -1
  204. package/.next/standalone/src/app/api/agents/route.ts +2 -2
  205. package/.next/standalone/src/app/api/projects/[id]/route.ts +10 -19
  206. package/.next/standalone/src/app/api/projects/route.ts +4 -10
  207. package/.next/standalone/src/app/api/specs/[name]/artifacts/[artifactType]/approve/route.ts +8 -8
  208. package/.next/standalone/src/app/api/specs/[name]/artifacts/[artifactType]/route.ts +14 -14
  209. package/.next/standalone/src/app/api/specs/[name]/promote/route.ts +17 -23
  210. package/.next/standalone/src/app/api/specs/[name]/route.ts +34 -36
  211. package/.next/standalone/src/app/api/specs/route.ts +10 -10
  212. package/.next/standalone/src/app/api/tasks/[id]/route.ts +11 -33
  213. package/.next/standalone/src/app/api/tasks/route.ts +3 -6
  214. package/.next/standalone/src/app/globals.css +3 -3
  215. package/.next/standalone/src/app/layout.tsx +9 -5
  216. package/.next/standalone/src/app/page.tsx +1 -1
  217. package/.next/standalone/src/app/specs/[name]/page.tsx +26 -68
  218. package/.next/standalone/src/components/kanban-board.tsx +78 -157
  219. package/.next/standalone/src/components/kanban-column.tsx +10 -12
  220. package/.next/standalone/src/components/markdown-preview.tsx +36 -19
  221. package/.next/standalone/src/components/providers.tsx +20 -0
  222. package/.next/standalone/src/components/specs/artifact-dag-status.tsx +12 -14
  223. package/.next/standalone/src/components/specs/artifact-editor.tsx +55 -26
  224. package/.next/standalone/src/components/specs/spec-detail.tsx +48 -40
  225. package/.next/standalone/src/components/specs/spec-kanban-column.tsx +49 -68
  226. package/.next/standalone/src/components/specs/spec-modal.tsx +119 -83
  227. package/.next/standalone/src/components/task-card.tsx +34 -38
  228. package/.next/standalone/src/components/task-dialog.tsx +16 -31
  229. package/.next/standalone/src/components/ui/badge.tsx +12 -18
  230. package/.next/standalone/src/components/ui/button.tsx +23 -28
  231. package/.next/standalone/src/components/ui/card.tsx +42 -62
  232. package/.next/standalone/src/components/ui/dialog.tsx +17 -35
  233. package/.next/standalone/src/db/index.ts +10 -10
  234. package/.next/standalone/src/db/schema.ts +37 -37
  235. package/.next/standalone/src/hooks/use-queries.ts +81 -0
  236. package/.next/standalone/src/hooks/use-websocket.ts +74 -0
  237. package/.next/standalone/src/lib/schema.test.ts +37 -37
  238. package/.next/standalone/src/lib/schema.ts +77 -31
  239. package/.next/standalone/src/lib/specs-dir.ts +8 -8
  240. package/.next/standalone/src/lib/specs.ts +98 -92
  241. package/.next/standalone/src/lib/utils.ts +2 -2
  242. package/.next/standalone/src/mcp/server.ts +556 -349
  243. package/.next/standalone/src/mcp/websocket.ts +26 -23
  244. package/.next/standalone/src/schemas/backend-api/templates/proposal.md +6 -4
  245. package/.next/standalone/src/schemas/backend-api/templates/tasks.md +6 -0
  246. package/.next/standalone/src/schemas/data-engineering/templates/proposal.md +6 -4
  247. package/.next/standalone/src/schemas/data-engineering/templates/tasks.md +6 -0
  248. package/.next/standalone/src/schemas/devops-platform/templates/proposal.md +6 -4
  249. package/.next/standalone/src/schemas/devops-platform/templates/tasks.md +6 -0
  250. package/.next/standalone/src/schemas/frontend-product/templates/proposal.md +6 -4
  251. package/.next/standalone/src/schemas/frontend-product/templates/tasks.md +6 -0
  252. package/.next/standalone/src/schemas/spec-driven/templates/proposal.md +6 -4
  253. package/.next/standalone/src/schemas/spec-driven/templates/tasks.md +26 -0
  254. package/.next/standalone/src/websocket/server.ts +20 -18
  255. package/.next/standalone/tsconfig.json +3 -12
  256. package/.next/standalone/tsconfig.tsbuildinfo +1 -1
  257. package/.next/static/chunks/4f23f64d46848f57.js +1 -0
  258. package/.next/static/chunks/53081dcdcad4f31e.js +1 -0
  259. package/.next/static/chunks/{6a3d582315f1c214.js → 701cfcbb41e0ab47.js} +1 -1
  260. package/.next/static/chunks/ac4b6b4d5b7e486e.css +1 -0
  261. package/.next/static/chunks/d0309ea872db5d9f.js +1 -0
  262. package/.next/static/chunks/d4cf8893a018e965.js +1 -0
  263. package/.next/static/chunks/e6c0233269a4bd69.js +13 -0
  264. package/.next/static/chunks/{7e65cfa9841f66a5.js → e7d83ce855afe416.js} +2 -2
  265. package/.next/static/chunks/ee7035560fc9e5e9.js +1 -0
  266. package/.next/static/chunks/{turbopack-f4d3806ab575051d.js → turbopack-8b3b66a22a5e0fb4.js} +2 -2
  267. package/README.md +166 -25
  268. package/bin/devflow.js +12 -5
  269. package/drizzle.config.ts +7 -7
  270. package/next.config.ts +11 -2
  271. package/package.json +16 -7
  272. package/scripts/init-db.js +3 -5
  273. package/scripts/init-db.test.js +6 -6
  274. package/scripts/init-schema.js +22 -22
  275. package/scripts/init-schema.test.js +45 -45
  276. package/scripts/install-environments.js +27 -8
  277. package/scripts/install-environments.test.js +19 -10
  278. package/scripts/install-skills.js +104 -31
  279. package/scripts/install-skills.test.js +6 -6
  280. package/src/app/api/agents/route.ts +2 -2
  281. package/src/app/api/projects/[id]/route.ts +10 -19
  282. package/src/app/api/projects/route.ts +4 -10
  283. package/src/app/api/specs/[name]/artifacts/[artifactType]/approve/route.ts +8 -8
  284. package/src/app/api/specs/[name]/artifacts/[artifactType]/route.ts +14 -14
  285. package/src/app/api/specs/[name]/promote/route.ts +17 -23
  286. package/src/app/api/specs/[name]/route.ts +34 -36
  287. package/src/app/api/specs/route.ts +10 -10
  288. package/src/app/api/tasks/[id]/route.ts +11 -33
  289. package/src/app/api/tasks/route.ts +3 -6
  290. package/src/app/globals.css +3 -3
  291. package/src/app/layout.tsx +9 -5
  292. package/src/app/page.tsx +1 -1
  293. package/src/app/specs/[name]/page.tsx +26 -68
  294. package/src/components/kanban-board.tsx +78 -157
  295. package/src/components/kanban-column.tsx +10 -12
  296. package/src/components/markdown-preview.tsx +36 -19
  297. package/src/components/providers.tsx +20 -0
  298. package/src/components/specs/artifact-dag-status.tsx +12 -14
  299. package/src/components/specs/artifact-editor.tsx +55 -26
  300. package/src/components/specs/spec-detail.tsx +48 -40
  301. package/src/components/specs/spec-kanban-column.tsx +49 -68
  302. package/src/components/specs/spec-modal.tsx +119 -83
  303. package/src/components/task-card.tsx +34 -38
  304. package/src/components/task-dialog.tsx +16 -31
  305. package/src/components/ui/badge.tsx +12 -18
  306. package/src/components/ui/button.tsx +23 -28
  307. package/src/components/ui/card.tsx +42 -62
  308. package/src/components/ui/dialog.tsx +17 -35
  309. package/src/db/index.ts +10 -10
  310. package/src/db/schema.ts +37 -37
  311. package/src/hooks/use-queries.ts +81 -0
  312. package/src/hooks/use-websocket.ts +74 -0
  313. package/src/lib/schema.test.ts +37 -37
  314. package/src/lib/schema.ts +77 -31
  315. package/src/lib/specs-dir.ts +8 -8
  316. package/src/lib/specs.ts +98 -92
  317. package/src/lib/utils.ts +2 -2
  318. package/src/mcp/server.ts +556 -349
  319. package/src/mcp/websocket.ts +26 -23
  320. package/src/schemas/backend-api/templates/proposal.md +6 -4
  321. package/src/schemas/backend-api/templates/tasks.md +6 -0
  322. package/src/schemas/data-engineering/templates/proposal.md +6 -4
  323. package/src/schemas/data-engineering/templates/tasks.md +6 -0
  324. package/src/schemas/devops-platform/templates/proposal.md +6 -4
  325. package/src/schemas/devops-platform/templates/tasks.md +6 -0
  326. package/src/schemas/frontend-product/templates/proposal.md +6 -4
  327. package/src/schemas/frontend-product/templates/tasks.md +6 -0
  328. package/src/schemas/spec-driven/templates/proposal.md +6 -4
  329. package/src/schemas/spec-driven/templates/tasks.md +26 -0
  330. package/src/types/bun-sqlite.d.ts +1 -1
  331. package/src/websocket/server.ts +20 -18
  332. package/tsconfig.json +3 -12
  333. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1be4e4b6._.js +0 -3
  334. package/.next/standalone/.next/server/chunks/[root-of-the-server]__492a4a24._.js +0 -3
  335. package/.next/standalone/.next/server/chunks/[root-of-the-server]__67c59ae1._.js +0 -3
  336. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6cc7aecd._.js +0 -3
  337. package/.next/standalone/.next/server/chunks/[root-of-the-server]__83a77b07._.js +0 -3
  338. package/.next/standalone/.next/server/chunks/[root-of-the-server]__88d91cb5._.js +0 -3
  339. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9e095e8._.js +0 -3
  340. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b367d327._.js +0 -3
  341. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eb413bbc._.js +0 -3
  342. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0b8c072a._.js +0 -3
  343. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12b2191f._.js +0 -3
  344. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15316462._.js +0 -3
  345. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19c9c409._.js +0 -3
  346. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19e5e22f._.js +0 -3
  347. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__25b5ccb3._.js +0 -3
  348. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__2f78c3da._.js +0 -3
  349. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3160b3f4._.js +0 -9
  350. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__319559be._.js +0 -3
  351. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__34f7cbcb._.js +0 -31
  352. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3abab94b._.js +0 -3
  353. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3b3d8930._.js +0 -3
  354. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4250799b._.js +0 -3
  355. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4c29cbc3._.js +0 -26
  356. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4e0bb6eb._.js +0 -9
  357. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__5678d2e3._.js +0 -3
  358. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__673445e0._.js +0 -31
  359. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__934de06b._.js +0 -3
  360. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__9b6c6f09._.js +0 -3
  361. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__a1b83a98._.js +0 -3
  362. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b00a15c5._.js +0 -3
  363. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b8567be3._.js +0 -26
  364. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__ce64536e._.js +0 -45
  365. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e96d33d2._.js +0 -45
  366. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__fd7ec054._.js +0 -3
  367. package/.next/standalone/.next/server/chunks/ssr/node_modules_16a3f9e7._.js +0 -17
  368. package/.next/standalone/.next/server/chunks/ssr/node_modules_45bce0e1._.js +0 -3
  369. package/.next/standalone/.next/server/chunks/ssr/node_modules_5e5a372d._.js +0 -17
  370. package/.next/standalone/.next/server/chunks/ssr/node_modules_6ece6f1e._.js +0 -3
  371. package/.next/standalone/.next/server/chunks/ssr/node_modules_d173e749._.js +0 -3
  372. package/.next/standalone/.next/server/chunks/ssr/node_modules_d3-shape_src_arc_fb1ac087.js +0 -3
  373. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_1f73a830._.js +0 -3
  374. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_663ac803._.js +0 -3
  375. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-FMBD7UC4_mjs_4f485529._.js +0 -17
  376. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_chunk-TZMSLE5B_mjs_8436a62a._.js +0 -3
  377. package/.next/standalone/.next/server/chunks/ssr/node_modules_mermaid_dist_chunks_mermaid_core_f78d2dc4._.js +0 -3
  378. package/.next/standalone/.next/server/chunks/ssr/src_app_layout_tsx_cc8184fa._.js +0 -3
  379. package/.next/standalone/devflow/specs/add-default-schema-template-selection/.approvals.json +0 -26
  380. package/.next/standalone/devflow/specs/add-default-schema-template-selection/.meta.json +0 -8
  381. package/.next/standalone/devflow/specs/add-default-schema-template-selection/design.md +0 -126
  382. package/.next/standalone/devflow/specs/add-default-schema-template-selection/proposal.md +0 -65
  383. package/.next/standalone/devflow/specs/add-default-schema-template-selection/specs.md +0 -107
  384. package/.next/standalone/devflow/specs/add-default-schema-template-selection/tasks.md +0 -235
  385. package/.next/standalone/devflow/specs/test-no-project/.approvals.json +0 -17
  386. package/.next/standalone/devflow/specs/test-no-project/.meta.json +0 -6
  387. package/.next/standalone/devflow/specs/ui-cleanup/.approvals.json +0 -29
  388. package/.next/standalone/devflow/specs/ui-cleanup/.meta.json +0 -6
  389. package/.next/standalone/devflow/specs/ui-cleanup/design.md +0 -49
  390. package/.next/standalone/devflow/specs/ui-cleanup/proposal.md +0 -34
  391. package/.next/standalone/devflow/specs/ui-cleanup/specs.md +0 -55
  392. package/.next/standalone/devflow/specs/ui-cleanup/tasks.md +0 -28
  393. package/.next/standalone/node_modules/@img/colour/color.cjs +0 -1594
  394. package/.next/standalone/node_modules/@img/colour/index.cjs +0 -1
  395. package/.next/standalone/node_modules/@img/colour/package.json +0 -45
  396. package/.next/standalone/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +0 -0
  397. package/.next/standalone/node_modules/@img/sharp-darwin-arm64/package.json +0 -40
  398. package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/README.md +0 -46
  399. package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/glib-2.0/include/glibconfig.h +0 -220
  400. package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/index.js +0 -1
  401. package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.8.17.3.dylib +0 -0
  402. package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/package.json +0 -36
  403. package/.next/standalone/node_modules/@img/sharp-libvips-darwin-arm64/versions.json +0 -30
  404. package/.next/standalone/node_modules/buffer-from/index.js +0 -72
  405. package/.next/standalone/node_modules/buffer-from/package.json +0 -19
  406. package/.next/standalone/node_modules/sharp/lib/channel.js +0 -177
  407. package/.next/standalone/node_modules/sharp/lib/colour.js +0 -195
  408. package/.next/standalone/node_modules/sharp/lib/composite.js +0 -212
  409. package/.next/standalone/node_modules/sharp/lib/constructor.js +0 -499
  410. package/.next/standalone/node_modules/sharp/lib/index.js +0 -16
  411. package/.next/standalone/node_modules/sharp/lib/input.js +0 -809
  412. package/.next/standalone/node_modules/sharp/lib/is.js +0 -143
  413. package/.next/standalone/node_modules/sharp/lib/libvips.js +0 -207
  414. package/.next/standalone/node_modules/sharp/lib/operation.js +0 -1016
  415. package/.next/standalone/node_modules/sharp/lib/output.js +0 -1666
  416. package/.next/standalone/node_modules/sharp/lib/resize.js +0 -595
  417. package/.next/standalone/node_modules/sharp/lib/sharp.js +0 -121
  418. package/.next/standalone/node_modules/sharp/lib/utility.js +0 -291
  419. package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/detect-libc.js +0 -313
  420. package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/elf.js +0 -39
  421. package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/filesystem.js +0 -51
  422. package/.next/standalone/node_modules/sharp/node_modules/detect-libc/lib/process.js +0 -24
  423. package/.next/standalone/node_modules/sharp/node_modules/semver/classes/comparator.js +0 -143
  424. package/.next/standalone/node_modules/sharp/node_modules/semver/classes/range.js +0 -557
  425. package/.next/standalone/node_modules/sharp/node_modules/semver/classes/semver.js +0 -333
  426. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/cmp.js +0 -54
  427. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/coerce.js +0 -62
  428. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/compare.js +0 -7
  429. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/eq.js +0 -5
  430. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gt.js +0 -5
  431. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gte.js +0 -5
  432. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lt.js +0 -5
  433. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lte.js +0 -5
  434. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/neq.js +0 -5
  435. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/parse.js +0 -18
  436. package/.next/standalone/node_modules/sharp/node_modules/semver/functions/satisfies.js +0 -12
  437. package/.next/standalone/node_modules/sharp/node_modules/semver/internal/constants.js +0 -37
  438. package/.next/standalone/node_modules/sharp/node_modules/semver/internal/debug.js +0 -11
  439. package/.next/standalone/node_modules/sharp/node_modules/semver/internal/identifiers.js +0 -29
  440. package/.next/standalone/node_modules/sharp/node_modules/semver/internal/lrucache.js +0 -42
  441. package/.next/standalone/node_modules/sharp/node_modules/semver/internal/parse-options.js +0 -17
  442. package/.next/standalone/node_modules/sharp/node_modules/semver/internal/re.js +0 -223
  443. package/.next/standalone/node_modules/sharp/node_modules/semver/package.json +0 -78
  444. package/.next/standalone/node_modules/sharp/package.json +0 -202
  445. package/.next/standalone/node_modules/source-map/lib/array-set.js +0 -121
  446. package/.next/standalone/node_modules/source-map/lib/base64-vlq.js +0 -140
  447. package/.next/standalone/node_modules/source-map/lib/base64.js +0 -67
  448. package/.next/standalone/node_modules/source-map/lib/binary-search.js +0 -111
  449. package/.next/standalone/node_modules/source-map/lib/mapping-list.js +0 -79
  450. package/.next/standalone/node_modules/source-map/lib/quick-sort.js +0 -114
  451. package/.next/standalone/node_modules/source-map/lib/source-map-consumer.js +0 -1145
  452. package/.next/standalone/node_modules/source-map/lib/source-map-generator.js +0 -425
  453. package/.next/standalone/node_modules/source-map/lib/source-node.js +0 -413
  454. package/.next/standalone/node_modules/source-map/lib/util.js +0 -488
  455. package/.next/standalone/node_modules/source-map/package.json +0 -73
  456. package/.next/standalone/node_modules/source-map/source-map.js +0 -8
  457. package/.next/standalone/node_modules/source-map-support/LICENSE.md +0 -21
  458. package/.next/standalone/node_modules/source-map-support/README.md +0 -284
  459. package/.next/standalone/node_modules/source-map-support/browser-source-map-support.js +0 -114
  460. package/.next/standalone/node_modules/source-map-support/package.json +0 -31
  461. package/.next/standalone/node_modules/source-map-support/register-hook-require.js +0 -1
  462. package/.next/standalone/node_modules/source-map-support/register.js +0 -1
  463. package/.next/standalone/node_modules/source-map-support/source-map-support.js +0 -625
  464. package/.next/standalone/node_modules/typescript/lib/_tsc.js +0 -133818
  465. package/.next/standalone/node_modules/typescript/lib/_tsserver.js +0 -659
  466. package/.next/standalone/node_modules/typescript/lib/_typingsInstaller.js +0 -222
  467. package/.next/standalone/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +0 -2122
  468. package/.next/standalone/node_modules/typescript/lib/de/diagnosticMessages.generated.json +0 -2122
  469. package/.next/standalone/node_modules/typescript/lib/es/diagnosticMessages.generated.json +0 -2122
  470. package/.next/standalone/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +0 -2122
  471. package/.next/standalone/node_modules/typescript/lib/it/diagnosticMessages.generated.json +0 -2122
  472. package/.next/standalone/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +0 -2122
  473. package/.next/standalone/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +0 -2122
  474. package/.next/standalone/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +0 -2122
  475. package/.next/standalone/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +0 -2122
  476. package/.next/standalone/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +0 -2122
  477. package/.next/standalone/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +0 -2122
  478. package/.next/standalone/node_modules/typescript/lib/tsc.js +0 -8
  479. package/.next/standalone/node_modules/typescript/lib/tsserver.js +0 -8
  480. package/.next/standalone/node_modules/typescript/lib/tsserverlibrary.js +0 -21
  481. package/.next/standalone/node_modules/typescript/lib/typesMap.json +0 -497
  482. package/.next/standalone/node_modules/typescript/lib/typescript.js +0 -200276
  483. package/.next/standalone/node_modules/typescript/lib/typingsInstaller.js +0 -8
  484. package/.next/standalone/node_modules/typescript/lib/watchGuard.js +0 -53
  485. package/.next/standalone/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +0 -2122
  486. package/.next/standalone/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +0 -2122
  487. package/.next/standalone/node_modules/typescript/package.json +0 -120
  488. package/.next/standalone/src/components/ui/collapsible.tsx +0 -12
  489. package/.next/standalone/src/components/ui/sheet.tsx +0 -130
  490. package/.next/standalone/src/components/ui/tabs.tsx +0 -58
  491. package/.next/static/chunks/0177331b8adf7346.js +0 -7
  492. package/.next/static/chunks/06af74e2f3e207c5.js +0 -7
  493. package/.next/static/chunks/1748d5cd2443723b.css +0 -1
  494. package/.next/static/chunks/7ae917cb100be2b9.js +0 -7
  495. package/.next/static/chunks/7c4b901b394c3a8c.js +0 -7
  496. package/src/components/ui/collapsible.tsx +0 -12
  497. package/src/components/ui/sheet.tsx +0 -130
  498. package/src/components/ui/tabs.tsx +0 -58
  499. /package/.next/standalone/node_modules/{detect-libc → libsql/node_modules/detect-libc}/lib/detect-libc.js +0 -0
  500. /package/.next/standalone/node_modules/{detect-libc → libsql/node_modules/detect-libc}/lib/filesystem.js +0 -0
  501. /package/.next/standalone/node_modules/{detect-libc → libsql/node_modules/detect-libc}/lib/process.js +0 -0
  502. /package/.next/static/{5YFrdIQd1UU2IxLxekrU9 → Ql6qo0GYLL23WRu6ec4N5}/_buildManifest.js +0 -0
  503. /package/.next/static/{5YFrdIQd1UU2IxLxekrU9 → Ql6qo0GYLL23WRu6ec4N5}/_clientMiddlewareManifest.json +0 -0
  504. /package/.next/static/{5YFrdIQd1UU2IxLxekrU9 → Ql6qo0GYLL23WRu6ec4N5}/_ssgManifest.js +0 -0
@@ -1,16 +1,16 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
- const yaml = require("js-yaml");
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const yaml = require('js-yaml');
4
4
 
5
5
  function getProjectConfigPath(projectRoot) {
6
- return path.join(projectRoot, ".devflow", "project-config.json");
6
+ return path.join(projectRoot, 'devflow', 'project-config.json');
7
7
  }
8
8
 
9
9
  function readProjectConfig(projectRoot) {
10
10
  const configPath = getProjectConfigPath(projectRoot);
11
11
  if (!fs.existsSync(configPath)) return {};
12
12
  try {
13
- return JSON.parse(fs.readFileSync(configPath, "utf-8"));
13
+ return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
14
14
  } catch {
15
15
  return {};
16
16
  }
@@ -19,7 +19,7 @@ function readProjectConfig(projectRoot) {
19
19
  function writeProjectConfig(projectRoot, config) {
20
20
  const configPath = getProjectConfigPath(projectRoot);
21
21
  fs.mkdirSync(path.dirname(configPath), { recursive: true });
22
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
22
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
23
23
  }
24
24
 
25
25
  function readSchemasFromDir(baseDir, source) {
@@ -31,9 +31,9 @@ function readSchemasFromDir(baseDir, source) {
31
31
 
32
32
  const schemas = [];
33
33
  for (const entryName of entries) {
34
- const schemaPath = path.join(baseDir, entryName, "schema.yaml");
34
+ const schemaPath = path.join(baseDir, entryName, 'schema.yaml');
35
35
  if (!fs.existsSync(schemaPath)) continue;
36
- const parsed = yaml.load(fs.readFileSync(schemaPath, "utf-8")) || {};
36
+ const parsed = yaml.load(fs.readFileSync(schemaPath, 'utf-8')) || {};
37
37
  if (!parsed.name) {
38
38
  throw new Error(`Invalid schema at ${schemaPath}: missing name`);
39
39
  }
@@ -41,7 +41,7 @@ function readSchemasFromDir(baseDir, source) {
41
41
  id: String(parsed.name),
42
42
  source,
43
43
  schemaPath,
44
- templatesDir: path.join(path.dirname(schemaPath), "templates"),
44
+ templatesDir: path.join(path.dirname(schemaPath), 'templates'),
45
45
  });
46
46
  }
47
47
  return schemas;
@@ -50,11 +50,11 @@ function readSchemasFromDir(baseDir, source) {
50
50
  function discoverSchemaTemplates(options) {
51
51
  const projectRoot = options.projectRoot;
52
52
  const packageRoot = options.packageRoot;
53
- const bundledDir = options.bundledDir || path.join(packageRoot, "src", "schemas");
54
- const projectSchemaDir = path.join(projectRoot, "schemas");
53
+ const bundledDir = options.bundledDir || path.join(packageRoot, 'src', 'schemas');
54
+ const projectSchemaDir = path.join(projectRoot, 'schemas');
55
55
 
56
- const bundled = readSchemasFromDir(bundledDir, "bundled");
57
- const project = readSchemasFromDir(projectSchemaDir, "project");
56
+ const bundled = readSchemasFromDir(bundledDir, 'bundled');
57
+ const project = readSchemasFromDir(projectSchemaDir, 'project');
58
58
  const merged = [...bundled, ...project];
59
59
 
60
60
  const idToSchema = new Map();
@@ -62,7 +62,7 @@ function discoverSchemaTemplates(options) {
62
62
  const existing = idToSchema.get(schema.id);
63
63
  if (existing) {
64
64
  throw new Error(
65
- `Schema ID conflict for "${schema.id}" between ${existing.source}:${existing.schemaPath} and ${schema.source}:${schema.schemaPath}`
65
+ `Schema ID conflict for "${schema.id}" between ${existing.source}:${existing.schemaPath} and ${schema.source}:${schema.schemaPath}`,
66
66
  );
67
67
  }
68
68
  idToSchema.set(schema.id, schema);
@@ -74,7 +74,7 @@ function discoverSchemaTemplates(options) {
74
74
  function assertKnownSchema(schemaId, availableSchemaIds) {
75
75
  if (!availableSchemaIds.includes(schemaId)) {
76
76
  throw new Error(
77
- `Unknown schema "${schemaId}". Available schemas: ${availableSchemaIds.join(", ")}`
77
+ `Unknown schema "${schemaId}". Available schemas: ${availableSchemaIds.join(', ')}`,
78
78
  );
79
79
  }
80
80
  }
@@ -91,31 +91,31 @@ async function resolveInitSchemaSelection(options) {
91
91
 
92
92
  if (requestedSchema) {
93
93
  assertKnownSchema(requestedSchema, availableSchemaIds);
94
- return { schemaId: requestedSchema, reason: "explicit" };
94
+ return { schemaId: requestedSchema, reason: 'explicit' };
95
95
  }
96
96
 
97
97
  if (!interactive) {
98
98
  if (existingDefaultSchema && availableSchemaIds.includes(existingDefaultSchema)) {
99
- return { schemaId: existingDefaultSchema, reason: "existing-default" };
99
+ return { schemaId: existingDefaultSchema, reason: 'existing-default' };
100
100
  }
101
- if (availableSchemaIds.includes("spec-driven")) {
102
- return { schemaId: "spec-driven", reason: "non-interactive-fallback" };
101
+ if (availableSchemaIds.includes('spec-driven')) {
102
+ return { schemaId: 'spec-driven', reason: 'non-interactive-fallback' };
103
103
  }
104
104
  throw new Error(
105
- `Non-interactive init requires a schema. Available schemas: ${availableSchemaIds.join(", ")}`
105
+ `Non-interactive init requires a schema. Available schemas: ${availableSchemaIds.join(', ')}`,
106
106
  );
107
107
  }
108
108
 
109
109
  if (existingDefaultSchema && availableSchemaIds.includes(existingDefaultSchema)) {
110
110
  const keep = (await confirmKeepExisting(existingDefaultSchema)) !== false;
111
111
  if (keep) {
112
- return { schemaId: existingDefaultSchema, reason: "existing-default-kept" };
112
+ return { schemaId: existingDefaultSchema, reason: 'existing-default-kept' };
113
113
  }
114
114
  }
115
115
 
116
116
  const selected = await promptSelectSchema(availableSchemaIds, existingDefaultSchema);
117
117
  assertKnownSchema(selected, availableSchemaIds);
118
- return { schemaId: selected, reason: "interactive-selection" };
118
+ return { schemaId: selected, reason: 'interactive-selection' };
119
119
  }
120
120
 
121
121
  module.exports = {
@@ -1,18 +1,18 @@
1
- const test = require("node:test");
2
- const assert = require("node:assert/strict");
3
- const fs = require("fs");
4
- const os = require("os");
5
- const path = require("path");
1
+ const test = require('node:test');
2
+ const assert = require('node:assert/strict');
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
6
 
7
7
  const {
8
8
  discoverSchemaTemplates,
9
9
  resolveInitSchemaSelection,
10
10
  readProjectConfig,
11
11
  writeProjectConfig,
12
- } = require("./init-schema");
12
+ } = require('./init-schema');
13
13
 
14
14
  function withTempDir(fn) {
15
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), "devflow-init-schema-"));
15
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'devflow-init-schema-'));
16
16
  try {
17
17
  return fn(dir);
18
18
  } finally {
@@ -22,82 +22,82 @@ function withTempDir(fn) {
22
22
 
23
23
  function writeSchema(baseDir, id) {
24
24
  const schemaDir = path.join(baseDir, id);
25
- fs.mkdirSync(path.join(schemaDir, "templates"), { recursive: true });
25
+ fs.mkdirSync(path.join(schemaDir, 'templates'), { recursive: true });
26
26
  fs.writeFileSync(
27
- path.join(schemaDir, "schema.yaml"),
27
+ path.join(schemaDir, 'schema.yaml'),
28
28
  `name: ${id}\nversion: 1\nartifacts: []\n`,
29
- "utf-8"
29
+ 'utf-8',
30
30
  );
31
31
  }
32
32
 
33
- test("resolveInitSchemaSelection respects explicit schema", async () => {
33
+ test('resolveInitSchemaSelection respects explicit schema', async () => {
34
34
  const result = await resolveInitSchemaSelection({
35
- requestedSchema: "backend-api",
36
- existingDefaultSchema: "spec-driven",
37
- availableSchemaIds: ["spec-driven", "backend-api"],
35
+ requestedSchema: 'backend-api',
36
+ existingDefaultSchema: 'spec-driven',
37
+ availableSchemaIds: ['spec-driven', 'backend-api'],
38
38
  interactive: false,
39
39
  });
40
- assert.equal(result.schemaId, "backend-api");
41
- assert.equal(result.reason, "explicit");
40
+ assert.equal(result.schemaId, 'backend-api');
41
+ assert.equal(result.reason, 'explicit');
42
42
  });
43
43
 
44
- test("resolveInitSchemaSelection keeps existing default in interactive mode", async () => {
44
+ test('resolveInitSchemaSelection keeps existing default in interactive mode', async () => {
45
45
  const result = await resolveInitSchemaSelection({
46
- existingDefaultSchema: "frontend-product",
47
- availableSchemaIds: ["frontend-product", "spec-driven"],
46
+ existingDefaultSchema: 'frontend-product',
47
+ availableSchemaIds: ['frontend-product', 'spec-driven'],
48
48
  interactive: true,
49
49
  confirmKeepExisting: async () => true,
50
- promptSelectSchema: async () => "spec-driven",
50
+ promptSelectSchema: async () => 'spec-driven',
51
51
  });
52
- assert.equal(result.schemaId, "frontend-product");
53
- assert.equal(result.reason, "existing-default-kept");
52
+ assert.equal(result.schemaId, 'frontend-product');
53
+ assert.equal(result.reason, 'existing-default-kept');
54
54
  });
55
55
 
56
- test("resolveInitSchemaSelection uses fallback in non-interactive mode", async () => {
56
+ test('resolveInitSchemaSelection uses fallback in non-interactive mode', async () => {
57
57
  const result = await resolveInitSchemaSelection({
58
- availableSchemaIds: ["spec-driven", "backend-api"],
58
+ availableSchemaIds: ['spec-driven', 'backend-api'],
59
59
  interactive: false,
60
60
  });
61
- assert.equal(result.schemaId, "spec-driven");
62
- assert.equal(result.reason, "non-interactive-fallback");
61
+ assert.equal(result.schemaId, 'spec-driven');
62
+ assert.equal(result.reason, 'non-interactive-fallback');
63
63
  });
64
64
 
65
- test("discoverSchemaTemplates returns bundled and project schemas", () =>
65
+ test('discoverSchemaTemplates returns bundled and project schemas', () =>
66
66
  withTempDir((root) => {
67
- const projectRoot = path.join(root, "project");
68
- const packageRoot = path.join(root, "package");
69
- const bundledDir = path.join(packageRoot, "src", "schemas");
70
- fs.mkdirSync(path.join(projectRoot, "schemas"), { recursive: true });
67
+ const projectRoot = path.join(root, 'project');
68
+ const packageRoot = path.join(root, 'package');
69
+ const bundledDir = path.join(packageRoot, 'src', 'schemas');
70
+ fs.mkdirSync(path.join(projectRoot, 'schemas'), { recursive: true });
71
71
  fs.mkdirSync(bundledDir, { recursive: true });
72
72
 
73
- writeSchema(bundledDir, "spec-driven");
74
- writeSchema(path.join(projectRoot, "schemas"), "custom-team");
73
+ writeSchema(bundledDir, 'spec-driven');
74
+ writeSchema(path.join(projectRoot, 'schemas'), 'custom-team');
75
75
 
76
76
  const schemas = discoverSchemaTemplates({ projectRoot, packageRoot, bundledDir });
77
77
  const ids = schemas.map((s) => s.id);
78
- assert.deepEqual(ids, ["custom-team", "spec-driven"]);
78
+ assert.deepEqual(ids, ['custom-team', 'spec-driven']);
79
79
  }));
80
80
 
81
- test("discoverSchemaTemplates fails on duplicate IDs", () =>
81
+ test('discoverSchemaTemplates fails on duplicate IDs', () =>
82
82
  withTempDir((root) => {
83
- const projectRoot = path.join(root, "project");
84
- const packageRoot = path.join(root, "package");
85
- const bundledDir = path.join(packageRoot, "src", "schemas");
86
- fs.mkdirSync(path.join(projectRoot, "schemas"), { recursive: true });
83
+ const projectRoot = path.join(root, 'project');
84
+ const packageRoot = path.join(root, 'package');
85
+ const bundledDir = path.join(packageRoot, 'src', 'schemas');
86
+ fs.mkdirSync(path.join(projectRoot, 'schemas'), { recursive: true });
87
87
  fs.mkdirSync(bundledDir, { recursive: true });
88
88
 
89
- writeSchema(bundledDir, "spec-driven");
90
- writeSchema(path.join(projectRoot, "schemas"), "spec-driven");
89
+ writeSchema(bundledDir, 'spec-driven');
90
+ writeSchema(path.join(projectRoot, 'schemas'), 'spec-driven');
91
91
 
92
92
  assert.throws(
93
93
  () => discoverSchemaTemplates({ projectRoot, packageRoot, bundledDir }),
94
- /Schema ID conflict/
94
+ /Schema ID conflict/,
95
95
  );
96
96
  }));
97
97
 
98
- test("project config read/write round-trip", () =>
98
+ test('project config read/write round-trip', () =>
99
99
  withTempDir((projectRoot) => {
100
- writeProjectConfig(projectRoot, { defaultSchemaTemplateId: "devops-platform" });
100
+ writeProjectConfig(projectRoot, { defaultSchemaTemplateId: 'devops-platform' });
101
101
  const cfg = readProjectConfig(projectRoot);
102
- assert.equal(cfg.defaultSchemaTemplateId, "devops-platform");
102
+ assert.equal(cfg.defaultSchemaTemplateId, 'devops-platform');
103
103
  }));
@@ -17,7 +17,14 @@ function parseTools(value) {
17
17
  const raw = (value ?? 'all').trim().toLowerCase();
18
18
  if (raw === 'none') return [];
19
19
  if (raw === 'all') return [...SUPPORTED_TOOLS];
20
- return [...new Set(raw.split(',').map(p => normalizeToolId(p.trim())).filter(Boolean))];
20
+ return [
21
+ ...new Set(
22
+ raw
23
+ .split(',')
24
+ .map((p) => normalizeToolId(p.trim()))
25
+ .filter(Boolean),
26
+ ),
27
+ ];
21
28
  }
22
29
 
23
30
  function defaultCommandExists(command) {
@@ -36,7 +43,7 @@ function buildDetectionContext(projectRoot, overrides = {}) {
36
43
  }
37
44
 
38
45
  function createDetectedEnvironment(id, signals) {
39
- const detected = signals.some(signal => signal.present);
46
+ const detected = signals.some((signal) => signal.present);
40
47
  return { id, detected, signals };
41
48
  }
42
49
 
@@ -46,7 +53,11 @@ function detectCodex(context) {
46
53
  : path.join(context.homedir, '.codex');
47
54
  return createDetectedEnvironment('codex', [
48
55
  { kind: 'binary', name: 'codex', present: context.commandExists('codex') },
49
- { kind: 'directory', name: path.join(context.projectRoot, '.codex'), present: context.pathExists(path.join(context.projectRoot, '.codex')) },
56
+ {
57
+ kind: 'directory',
58
+ name: path.join(context.projectRoot, '.codex'),
59
+ present: context.pathExists(path.join(context.projectRoot, '.codex')),
60
+ },
50
61
  { kind: 'directory', name: codexHome, present: context.pathExists(codexHome) },
51
62
  ]);
52
63
  }
@@ -54,8 +65,16 @@ function detectCodex(context) {
54
65
  function detectClaudeCode(context) {
55
66
  return createDetectedEnvironment('claudecode', [
56
67
  { kind: 'binary', name: 'claude', present: context.commandExists('claude') },
57
- { kind: 'directory', name: path.join(context.projectRoot, '.claude'), present: context.pathExists(path.join(context.projectRoot, '.claude')) },
58
- { kind: 'directory', name: path.join(context.homedir, '.claude'), present: context.pathExists(path.join(context.homedir, '.claude')) },
68
+ {
69
+ kind: 'directory',
70
+ name: path.join(context.projectRoot, '.claude'),
71
+ present: context.pathExists(path.join(context.projectRoot, '.claude')),
72
+ },
73
+ {
74
+ kind: 'directory',
75
+ name: path.join(context.homedir, '.claude'),
76
+ present: context.pathExists(path.join(context.homedir, '.claude')),
77
+ },
59
78
  ]);
60
79
  }
61
80
 
@@ -69,13 +88,13 @@ function getEnvironmentDetectors() {
69
88
  function detectEnvironments(projectRoot, overrides = {}) {
70
89
  const context = buildDetectionContext(projectRoot, overrides);
71
90
  const detectors = getEnvironmentDetectors();
72
- return SUPPORTED_TOOLS.map(tool => detectors[tool].detect(context));
91
+ return SUPPORTED_TOOLS.map((tool) => detectors[tool].detect(context));
73
92
  }
74
93
 
75
94
  function detectInstalledTools(projectRoot, overrides = {}) {
76
95
  return detectEnvironments(projectRoot, overrides)
77
- .filter(result => result.detected)
78
- .map(result => result.id);
96
+ .filter((result) => result.detected)
97
+ .map((result) => result.id);
79
98
  }
80
99
 
81
100
  function getToolAdapters() {
@@ -13,7 +13,7 @@ const HOME_DIR = '/home/tester';
13
13
 
14
14
  function detectionHarness({ commands = [], paths = [] } = {}) {
15
15
  const commandSet = new Set(commands);
16
- const pathSet = new Set(paths.map(p => path.resolve(p)));
16
+ const pathSet = new Set(paths.map((p) => path.resolve(p)));
17
17
  return {
18
18
  commandExists: (command) => commandSet.has(command),
19
19
  pathExists: (targetPath) => pathSet.has(path.resolve(targetPath)),
@@ -23,23 +23,32 @@ function detectionHarness({ commands = [], paths = [] } = {}) {
23
23
  }
24
24
 
25
25
  test('detectInstalledTools returns claudecode when only Claude signals are present', () => {
26
- const detected = detectInstalledTools(PROJECT_ROOT, detectionHarness({
27
- commands: ['claude'],
28
- }));
26
+ const detected = detectInstalledTools(
27
+ PROJECT_ROOT,
28
+ detectionHarness({
29
+ commands: ['claude'],
30
+ }),
31
+ );
29
32
  assert.deepEqual(detected, ['claudecode']);
30
33
  });
31
34
 
32
35
  test('detectInstalledTools returns codex when only Codex signals are present', () => {
33
- const detected = detectInstalledTools(PROJECT_ROOT, detectionHarness({
34
- commands: ['codex'],
35
- }));
36
+ const detected = detectInstalledTools(
37
+ PROJECT_ROOT,
38
+ detectionHarness({
39
+ commands: ['codex'],
40
+ }),
41
+ );
36
42
  assert.deepEqual(detected, ['codex']);
37
43
  });
38
44
 
39
45
  test('detectInstalledTools returns both tools when both signals are present', () => {
40
- const detected = detectInstalledTools(PROJECT_ROOT, detectionHarness({
41
- commands: ['codex', 'claude'],
42
- }));
46
+ const detected = detectInstalledTools(
47
+ PROJECT_ROOT,
48
+ detectionHarness({
49
+ commands: ['codex', 'claude'],
50
+ }),
51
+ );
43
52
  assert.deepEqual(detected, ['codex', 'claudecode']);
44
53
  });
45
54
 
@@ -2,15 +2,11 @@
2
2
 
3
3
  const path = require('path');
4
4
  const fs = require('fs');
5
- const {
6
- parseTools,
7
- getToolAdapter,
8
- detectEnvironments,
9
- } = require('./install-environments');
5
+ const { parseTools, getToolAdapter, detectEnvironments } = require('./install-environments');
10
6
 
11
7
  const MANAGED_BEGIN = '<!-- DEVFLOW:BEGIN ';
12
8
  const MANAGED_END = '<!-- DEVFLOW:END ';
13
- const COMMAND_SET = ['new', 'continue', 'status', 'promote', 'develop', 'archive'];
9
+ const COMMAND_SET = ['new', 'continue', 'status', 'promote', 'develop', 'archive', 'schema'];
14
10
 
15
11
  function resolveToolDirs(projectRoot, tool) {
16
12
  return getToolAdapter(tool).resolveTargets(projectRoot);
@@ -138,6 +134,44 @@ function renderSkill(tool, command, markerId) {
138
134
  '4. Call `archive_spec`.',
139
135
  '5. Report success and the archive path.',
140
136
  ],
137
+ schema: [
138
+ `# Skill: /df:schema`,
139
+ '',
140
+ `Use this skill to interactively create a custom DevFlow schema in ${agentName}.`,
141
+ '',
142
+ '## Steps (in order)',
143
+ '',
144
+ '1. Call `list_schemas` and show the user what schemas are already available.',
145
+ ' If one fits their needs, suggest using it directly.',
146
+ '2. Ask what kind of project/workflow they need (e.g. mobile app, ML pipeline,',
147
+ ' infrastructure, documentation, data engineering, security review, etc.).',
148
+ '3. Based on the project type, ask which artifacts/documents their workflow',
149
+ ' should include. Suggest sensible defaults. Common options:',
150
+ ' - Proposal / RFC',
151
+ ' - Requirements / Specifications',
152
+ ' - Architecture / Design doc',
153
+ ' - Security review',
154
+ ' - Testing plan / Test strategy',
155
+ ' - Migration plan',
156
+ ' - Deployment / Runbook',
157
+ ' - Implementation tasks',
158
+ '4. Design the artifact dependency DAG — which artifacts must be approved',
159
+ ' before others can be written. Present the DAG to the user for confirmation.',
160
+ '5. Ask about quality rules:',
161
+ ' - RFC 2119 keywords enforced (MUST/SHOULD/MAY)?',
162
+ ' - Minimum scenarios per requirement (suggest 1-2)?',
163
+ '6. Generate well-structured markdown templates for each artifact.',
164
+ '7. Call `create_schema` with name, artifacts, qualityRules, apply, and templates.',
165
+ '8. Report the schema was created and how to use it:',
166
+ ' - `create_spec` with `schema: "<name>"`',
167
+ ' - Or set as default in `devflow/project-config.json`',
168
+ '',
169
+ '## Guidelines',
170
+ '- Keep artifact IDs short and kebab-case (e.g. "security-review", "test-plan")',
171
+ '- Template filenames should match: `<artifact-id>.md`',
172
+ '- Always include a final "tasks" artifact that depends on the key artifacts',
173
+ '- The `apply.requires` should include at minimum the tasks artifact',
174
+ ],
141
175
  };
142
176
 
143
177
  const lines = bodies[command];
@@ -147,9 +181,10 @@ function renderSkill(tool, command, markerId) {
147
181
 
148
182
  function renderCommand(tool, command, markerId) {
149
183
  const commandName = `/df:${command}`;
150
- const codexHeader = tool === 'codex'
151
- ? ['---', `description: DevFlow ${commandName} workflow action`, '---', '']
152
- : [];
184
+ const codexHeader =
185
+ tool === 'codex'
186
+ ? ['---', `description: DevFlow ${commandName} workflow action`, '---', '']
187
+ : [];
153
188
 
154
189
  const bodies = {
155
190
  new: [
@@ -262,6 +297,24 @@ function renderCommand(tool, command, markerId) {
262
297
  '4. Call `archive_spec`.',
263
298
  '5. Report success and the archive path.',
264
299
  ],
300
+ schema: [
301
+ `# ${commandName}`,
302
+ '',
303
+ 'Interactively create a custom DevFlow schema.',
304
+ '',
305
+ '## Steps (in order)',
306
+ '',
307
+ '1. Call `list_schemas` and show available schemas. If one fits, suggest it.',
308
+ '2. Ask what kind of project/workflow the user needs.',
309
+ '3. Ask which artifacts/documents their workflow should include.',
310
+ '4. Design the artifact dependency DAG. Present it for confirmation.',
311
+ '5. Ask about quality rules (RFC 2119, min scenarios per requirement).',
312
+ '6. Generate markdown templates for each artifact.',
313
+ '7. Call `create_schema` with name, artifacts, qualityRules, apply, and templates.',
314
+ '8. Report the schema was created and how to use it:',
315
+ ' - `create_spec` with `schema: "<name>"`',
316
+ ' - Or set as default in `devflow/project-config.json`',
317
+ ],
265
318
  };
266
319
 
267
320
  const bodyLines = bodies[command];
@@ -273,7 +326,7 @@ function replaceManagedSection(existing, markerId, nextContent) {
273
326
  const escaped = markerId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
274
327
  const pattern = new RegExp(
275
328
  `<!-- DEVFLOW:BEGIN ${escaped} -->[\\s\\S]*?<!-- DEVFLOW:END ${escaped} -->\\n?`,
276
- 'm'
329
+ 'm',
277
330
  );
278
331
  if (!pattern.test(existing)) return null;
279
332
  return existing.replace(pattern, nextContent);
@@ -300,7 +353,9 @@ function buildAssets(projectRoot, tools, delivery) {
300
353
  const commandMarker = `${tool}:command:df-${command}`;
301
354
  if (delivery !== 'commands') {
302
355
  assets.push({
303
- tool, kind: 'skill', command,
356
+ tool,
357
+ kind: 'skill',
358
+ command,
304
359
  outputPath: path.join(dirs.skillsDir, `df-${command}.md`),
305
360
  markerId: skillMarker,
306
361
  content: renderSkill(tool, command, skillMarker),
@@ -308,7 +363,9 @@ function buildAssets(projectRoot, tools, delivery) {
308
363
  }
309
364
  if (delivery !== 'skills') {
310
365
  assets.push({
311
- tool, kind: 'command', command,
366
+ tool,
367
+ kind: 'command',
368
+ command,
312
369
  outputPath: path.join(dirs.commandsDir, `df-${command}.md`),
313
370
  markerId: commandMarker,
314
371
  content: renderCommand(tool, command, commandMarker),
@@ -329,7 +386,7 @@ function selectTools(projectRoot, options) {
329
386
  } else if (options.tools !== undefined) {
330
387
  selectedTools = parseTools(options.tools);
331
388
  } else if (autodetect) {
332
- selectedTools = detection.filter(d => d.detected).map(d => d.id);
389
+ selectedTools = detection.filter((d) => d.detected).map((d) => d.id);
333
390
  } else {
334
391
  selectedTools = parseTools('all');
335
392
  }
@@ -354,17 +411,17 @@ function installSkills(projectRoot, options = {}) {
354
411
  dryRun,
355
412
  autodetect: selection.autodetect,
356
413
  selectedTools: selection.selectedTools,
357
- environments: selection.detection.map(d => ({
414
+ environments: selection.detection.map((d) => ({
358
415
  tool: d.id,
359
416
  detected: d.detected,
360
- status: selection.selectedTools.includes(d.id)
361
- ? (dryRun ? 'planned' : 'pending')
362
- : 'skipped',
417
+ status: selection.selectedTools.includes(d.id) ? (dryRun ? 'planned' : 'pending') : 'skipped',
363
418
  reason: selection.selectedTools.includes(d.id)
364
419
  ? undefined
365
- : (selection.autodetect && options.tools === undefined && !options.only
366
- ? (d.detected ? 'not-selected' : 'not-detected')
367
- : 'not-selected'),
420
+ : selection.autodetect && options.tools === undefined && !options.only
421
+ ? d.detected
422
+ ? 'not-selected'
423
+ : 'not-detected'
424
+ : 'not-selected',
368
425
  created: 0,
369
426
  updated: 0,
370
427
  skipped: 0,
@@ -378,7 +435,7 @@ function installSkills(projectRoot, options = {}) {
378
435
 
379
436
  for (const asset of assets) {
380
437
  const { outputPath, markerId, content, tool } = asset;
381
- const envReport = report.environments.find(e => e.tool === tool);
438
+ const envReport = report.environments.find((e) => e.tool === tool);
382
439
  const displayPath = path.relative(projectRoot, outputPath);
383
440
  try {
384
441
  const alreadyExists = exists(outputPath);
@@ -393,7 +450,11 @@ function installSkills(projectRoot, options = {}) {
393
450
  }
394
451
  report.updated++;
395
452
  if (envReport) envReport.updated++;
396
- report.results.push({ ...asset, path: displayPath, action: dryRun ? 'would_update' : 'updated' });
453
+ report.results.push({
454
+ ...asset,
455
+ path: displayPath,
456
+ action: dryRun ? 'would_update' : 'updated',
457
+ });
397
458
  } else {
398
459
  report.skipped++;
399
460
  if (envReport) envReport.skipped++;
@@ -403,7 +464,7 @@ function installSkills(projectRoot, options = {}) {
403
464
  }
404
465
 
405
466
  const ownershipError = new Error(
406
- `Refusing to modify unmanaged file for ${tool}: ${displayPath}`
467
+ `Refusing to modify unmanaged file for ${tool}: ${displayPath}`,
407
468
  );
408
469
  ownershipError.code = 'UNMANAGED_FILE';
409
470
  throw ownershipError;
@@ -414,7 +475,11 @@ function installSkills(projectRoot, options = {}) {
414
475
  }
415
476
  report.created++;
416
477
  if (envReport) envReport.created++;
417
- report.results.push({ ...asset, path: displayPath, action: dryRun ? 'would_create' : 'created' });
478
+ report.results.push({
479
+ ...asset,
480
+ path: displayPath,
481
+ action: dryRun ? 'would_create' : 'created',
482
+ });
418
483
  } catch (error) {
419
484
  report.failed++;
420
485
  if (envReport) envReport.failed++;
@@ -432,7 +497,8 @@ function installSkills(projectRoot, options = {}) {
432
497
  if (!selection.selectedTools.includes(envReport.tool)) continue;
433
498
  if (envReport.failed > 0) {
434
499
  envReport.status = 'failed';
435
- envReport.reason = envReport.created + envReport.updated > 0 ? 'partial-failure' : 'install-failed';
500
+ envReport.reason =
501
+ envReport.created + envReport.updated > 0 ? 'partial-failure' : 'install-failed';
436
502
  } else if (dryRun) {
437
503
  envReport.status = 'planned';
438
504
  } else {
@@ -449,22 +515,29 @@ function printReport(report) {
449
515
  for (const env of report.environments) {
450
516
  const statusDetails = env.reason ? `${env.status} (${env.reason})` : env.status;
451
517
  const detectedText = env.detected ? 'detected' : 'not detected';
452
- console.log(` - ${env.tool}: ${statusDetails}; ${detectedText}; created=${env.created} updated=${env.updated} skipped=${env.skipped} failed=${env.failed}`);
518
+ console.log(
519
+ ` - ${env.tool}: ${statusDetails}; ${detectedText}; created=${env.created} updated=${env.updated} skipped=${env.skipped} failed=${env.failed}`,
520
+ );
453
521
  }
454
522
  console.log('');
455
523
  }
456
524
 
457
525
  for (const r of report.results) {
458
526
  const icon =
459
- r.action === 'created' || r.action === 'would_create' ? '✓' :
460
- r.action === 'updated' || r.action === 'would_update' ? '' :
461
- r.action === 'failed' ? '' :
462
- '';
527
+ r.action === 'created' || r.action === 'would_create'
528
+ ? ''
529
+ : r.action === 'updated' || r.action === 'would_update'
530
+ ? ''
531
+ : r.action === 'failed'
532
+ ? '✗'
533
+ : '–';
463
534
  const errorSuffix = r.action === 'failed' ? ` - ${r.error}` : '';
464
535
  console.log(` ${icon} [${r.tool}] ${r.kind} ${r.path} (${r.action})${errorSuffix}`);
465
536
  }
466
537
  const mode = report.dryRun ? ' (dry-run)' : '';
467
- console.log(`\n ${report.created} created, ${report.updated} updated, ${report.skipped} skipped, ${report.failed} failed${mode}`);
538
+ console.log(
539
+ `\n ${report.created} created, ${report.updated} updated, ${report.skipped} skipped, ${report.failed} failed${mode}`,
540
+ );
468
541
  }
469
542
 
470
543
  // CLI usage: node scripts/install-skills.js [--tools all|codex|claudecode] [--delivery both|skills|commands] [--force]