ai-spector 0.9.21 → 0.9.24

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 (579) hide show
  1. package/contracts/bootstrap/config/prototype-screen-map.json +25 -0
  2. package/contracts/bootstrap/config/prototype.config.json +17 -0
  3. package/contracts/bootstrap/config/review-queue-pending.json +4 -0
  4. package/contracts/bootstrap/config/review-queue-registry.json +4 -0
  5. package/contracts/bootstrap/config/review.config.json +5 -0
  6. package/contracts/bootstrap/docs/ENTITY_REGISTRY_MIGRATION.md +192 -0
  7. package/contracts/bootstrap/docs/MIGRATION.md +463 -0
  8. package/contracts/bootstrap/docs/README.md +48 -0
  9. package/contracts/bootstrap/docs/adapters/README.md +32 -0
  10. package/contracts/bootstrap/docs/guides/COMMENTS_ENTITY_MIGRATION.md +195 -0
  11. package/contracts/bootstrap/docs/guides/DOCOPS_MANUAL_FALLBACK.md +177 -0
  12. package/contracts/bootstrap/docs/guides/PROJECT_LAYOUT.md +84 -0
  13. package/contracts/bootstrap/docs/modules/comments.md +77 -0
  14. package/contracts/bootstrap/docs/modules/generate.md +25 -0
  15. package/contracts/bootstrap/docs/modules/graph.md +31 -0
  16. package/contracts/bootstrap/docs/modules/prototype.md +26 -0
  17. package/contracts/bootstrap/docs/modules/review.md +25 -0
  18. package/contracts/bootstrap/docs/modules/translate.md +26 -0
  19. package/contracts/bootstrap/scripts/migrate-entity-registry.sh +55 -0
  20. package/contracts/bootstrap/templates/basic-design/db-design-template.md +177 -0
  21. package/contracts/bootstrap/templates/basic-design/detail-api-template.md +278 -0
  22. package/contracts/bootstrap/templates/basic-design/detail-screen-template.md +281 -0
  23. package/contracts/bootstrap/templates/basic-design/list-api-template.md +130 -0
  24. package/contracts/bootstrap/templates/basic-design/list-screen-template.md +242 -0
  25. package/contracts/bootstrap/templates/detail-design/common/architecture-overview-template.md +302 -0
  26. package/contracts/bootstrap/templates/detail-design/common/deployment-infrastructure-template.md +461 -0
  27. package/contracts/bootstrap/templates/detail-design/common/error-handling-patterns-template.md +460 -0
  28. package/contracts/bootstrap/templates/detail-design/common/integration-patterns-template.md +410 -0
  29. package/contracts/bootstrap/templates/detail-design/common/performance-standards-template.md +406 -0
  30. package/contracts/bootstrap/templates/detail-design/common/security-patterns-template.md +395 -0
  31. package/contracts/bootstrap/templates/detail-design/feature-detail-design-template.md +773 -0
  32. package/contracts/bootstrap/templates/detail-design/feature-list-template.md +39 -0
  33. package/contracts/bootstrap/templates/srs/1-introduction.md +58 -0
  34. package/contracts/bootstrap/templates/srs/2-overall-description.md +91 -0
  35. package/contracts/bootstrap/templates/srs/3-use-case-detail-template.md +142 -0
  36. package/contracts/bootstrap/templates/srs/3-use-cases.md +53 -0
  37. package/contracts/bootstrap/templates/srs/4-system-feature-detail-template.md +131 -0
  38. package/contracts/bootstrap/templates/srs/4-system-features-list-template.md +39 -0
  39. package/contracts/bootstrap/templates/srs/5-data-requirements.md +59 -0
  40. package/contracts/bootstrap/templates/srs/6-external-interfaces.md +56 -0
  41. package/contracts/bootstrap/templates/srs/7-quality-attributes.md +74 -0
  42. package/contracts/bootstrap/templates/srs/8-internationalization.md +36 -0
  43. package/contracts/bootstrap/templates/srs/9-other-requirements.md +46 -0
  44. package/contracts/examples/full-docops.config.json +54 -0
  45. package/contracts/examples/migrate-lifecycle.json +18 -0
  46. package/contracts/examples/minimal-comment-thread/comment-root.json +10 -0
  47. package/contracts/examples/minimal-comment-thread/meta_data.json +22 -0
  48. package/contracts/examples/minimal-docops.config.json +33 -0
  49. package/contracts/examples/minimal-lifecycle.json +17 -0
  50. package/contracts/examples/minimal-prototype.config.json +18 -0
  51. package/contracts/examples/minimal-screen-map.json +25 -0
  52. package/contracts/examples/registry/minimal-document.entity.json +15 -0
  53. package/contracts/examples/registry/minimal-manifest.json +7 -0
  54. package/contracts/examples/registry/minimal-screen.entity.json +11 -0
  55. package/contracts/examples/review/minimal-pending.json +14 -0
  56. package/contracts/examples/review/minimal-registry.json +31 -0
  57. package/contracts/examples/review/minimal-review.config.json +7 -0
  58. package/contracts/schemas/comments/comment_body.schema.json +19 -0
  59. package/contracts/schemas/comments/meta_data.schema.json +59 -0
  60. package/contracts/schemas/docops.config.schema.json +97 -0
  61. package/contracts/schemas/lifecycle.schema.json +43 -0
  62. package/contracts/schemas/prototype/config.schema.json +56 -0
  63. package/contracts/schemas/prototype/screen-map.schema.json +51 -0
  64. package/contracts/schemas/registry/document.entity.schema.json +38 -0
  65. package/contracts/schemas/registry/manifest.schema.json +18 -0
  66. package/contracts/schemas/registry/screen.entity.schema.json +28 -0
  67. package/contracts/schemas/review/registry.schema.json +72 -0
  68. package/contracts/schemas/review/review.config.schema.json +42 -0
  69. package/dist/cli.js +26 -1
  70. package/dist/cli.js.map +1 -1
  71. package/dist/core/docops/bootstrap.d.ts +4 -1
  72. package/dist/core/docops/bootstrap.d.ts.map +1 -1
  73. package/dist/core/docops/bootstrap.js +16 -9
  74. package/dist/core/docops/bootstrap.js.map +1 -1
  75. package/dist/core/docops/guide.d.ts +78 -0
  76. package/dist/core/docops/guide.d.ts.map +1 -0
  77. package/dist/core/docops/guide.js +554 -0
  78. package/dist/core/docops/guide.js.map +1 -0
  79. package/dist/core/docops/migrate.d.ts.map +1 -1
  80. package/dist/core/docops/migrate.js +40 -6
  81. package/dist/core/docops/migrate.js.map +1 -1
  82. package/dist/core/graph/doc-extract.d.ts.map +1 -1
  83. package/dist/core/graph/doc-extract.js +12 -0
  84. package/dist/core/graph/doc-extract.js.map +1 -1
  85. package/dist/core/graph/impact.d.ts.map +1 -1
  86. package/dist/core/graph/impact.js +2 -1
  87. package/dist/core/graph/impact.js.map +1 -1
  88. package/dist/core/graph/link-testcases.d.ts +14 -0
  89. package/dist/core/graph/link-testcases.d.ts.map +1 -0
  90. package/dist/core/graph/link-testcases.js +46 -0
  91. package/dist/core/graph/link-testcases.js.map +1 -0
  92. package/dist/core/operations/docops.d.ts +8 -0
  93. package/dist/core/operations/docops.d.ts.map +1 -1
  94. package/dist/core/operations/docops.js +40 -0
  95. package/dist/core/operations/docops.js.map +1 -1
  96. package/dist/core/operations/index.d.ts.map +1 -1
  97. package/dist/core/operations/index.js +25 -0
  98. package/dist/core/operations/index.js.map +1 -1
  99. package/dist/core/operations/task-gates.d.ts +8 -1
  100. package/dist/core/operations/task-gates.d.ts.map +1 -1
  101. package/dist/core/operations/task-gates.js +14 -0
  102. package/dist/core/operations/task-gates.js.map +1 -1
  103. package/dist/core/operations/task.d.ts +2 -0
  104. package/dist/core/operations/task.d.ts.map +1 -1
  105. package/dist/core/operations/task.js +40 -2
  106. package/dist/core/operations/task.js.map +1 -1
  107. package/dist/core/sync/audit.d.ts.map +1 -1
  108. package/dist/core/sync/audit.js +14 -6
  109. package/dist/core/sync/audit.js.map +1 -1
  110. package/dist/core/sync/baseline.d.ts.map +1 -1
  111. package/dist/core/sync/baseline.js +5 -2
  112. package/dist/core/sync/baseline.js.map +1 -1
  113. package/dist/core/sync/constants.d.ts.map +1 -1
  114. package/dist/core/sync/constants.js +2 -1
  115. package/dist/core/sync/constants.js.map +1 -1
  116. package/dist/core/sync/gaps.d.ts.map +1 -1
  117. package/dist/core/sync/gaps.js +23 -2
  118. package/dist/core/sync/gaps.js.map +1 -1
  119. package/dist/core/sync/git-diff.d.ts +1 -0
  120. package/dist/core/sync/git-diff.d.ts.map +1 -1
  121. package/dist/core/sync/git-diff.js +14 -0
  122. package/dist/core/sync/git-diff.js.map +1 -1
  123. package/dist/core/sync/repo-context.d.ts +23 -0
  124. package/dist/core/sync/repo-context.d.ts.map +1 -0
  125. package/dist/core/sync/repo-context.js +28 -0
  126. package/dist/core/sync/repo-context.js.map +1 -0
  127. package/dist/core/sync/snapshot.d.ts.map +1 -1
  128. package/dist/core/sync/snapshot.js +24 -18
  129. package/dist/core/sync/snapshot.js.map +1 -1
  130. package/dist/core/sync/types.d.ts +7 -2
  131. package/dist/core/sync/types.d.ts.map +1 -1
  132. package/dist/core/upgrade/checklist.json +2 -2
  133. package/dist/interfaces/mcp/schemas.d.ts +2 -0
  134. package/dist/interfaces/mcp/schemas.d.ts.map +1 -1
  135. package/dist/interfaces/mcp/schemas.js +4 -0
  136. package/dist/interfaces/mcp/schemas.js.map +1 -1
  137. package/dist/interfaces/mcp/server.js +0 -0
  138. package/dist/types.d.ts +2 -2
  139. package/dist/types.d.ts.map +1 -1
  140. package/package.json +2 -1
  141. package/scaffold/claude/.claude/skills/_skill-router.md +11 -8
  142. package/scaffold/claude/.claude/skills/ai-spector/references/cli-failures.md +3 -3
  143. package/scaffold/claude/.claude/skills/ai-spector/references/docops-migrate.md +112 -0
  144. package/scaffold/claude/.claude/skills/ai-spector/references/help.md +1 -1
  145. package/scaffold/claude/.claude/skills/ai-spector/references/runbook.md +49 -26
  146. package/scaffold/claude/.claude/skills/ai-spector/skill.md +3 -2
  147. package/scaffold/cursor/skills/_skill-router.md +11 -8
  148. package/scaffold/cursor/skills/ai-spector/SKILL.md +3 -2
  149. package/scaffold/cursor/skills/ai-spector/references/cli-failures.md +3 -3
  150. package/scaffold/cursor/skills/ai-spector/references/docops-migrate.md +112 -0
  151. package/scaffold/cursor/skills/ai-spector/references/help.md +1 -1
  152. package/scaffold/cursor/skills/ai-spector/references/runbook.md +49 -26
  153. package/schemas/rules.impact.json +3 -2
  154. package/schemas/schema.graph.json +4 -2
  155. package/dist/commands/analyze.d.ts +0 -12
  156. package/dist/commands/analyze.d.ts.map +0 -1
  157. package/dist/commands/analyze.js +0 -53
  158. package/dist/commands/analyze.js.map +0 -1
  159. package/dist/commands/bootstrap.d.ts +0 -4
  160. package/dist/commands/bootstrap.d.ts.map +0 -1
  161. package/dist/commands/bootstrap.js +0 -58
  162. package/dist/commands/bootstrap.js.map +0 -1
  163. package/dist/commands/comments.d.ts +0 -44
  164. package/dist/commands/comments.d.ts.map +0 -1
  165. package/dist/commands/comments.js +0 -79
  166. package/dist/commands/comments.js.map +0 -1
  167. package/dist/commands/graph-impact.d.ts +0 -28
  168. package/dist/commands/graph-impact.d.ts.map +0 -1
  169. package/dist/commands/graph-impact.js +0 -174
  170. package/dist/commands/graph-impact.js.map +0 -1
  171. package/dist/commands/graph-merge.d.ts +0 -32
  172. package/dist/commands/graph-merge.d.ts.map +0 -1
  173. package/dist/commands/graph-merge.js +0 -101
  174. package/dist/commands/graph-merge.js.map +0 -1
  175. package/dist/commands/graph-query.d.ts +0 -10
  176. package/dist/commands/graph-query.d.ts.map +0 -1
  177. package/dist/commands/graph-query.js +0 -24
  178. package/dist/commands/graph-query.js.map +0 -1
  179. package/dist/commands/graph-report.d.ts +0 -9
  180. package/dist/commands/graph-report.d.ts.map +0 -1
  181. package/dist/commands/graph-report.js +0 -10
  182. package/dist/commands/graph-report.js.map +0 -1
  183. package/dist/commands/graph-visualize.d.ts +0 -17
  184. package/dist/commands/graph-visualize.d.ts.map +0 -1
  185. package/dist/commands/graph-visualize.js +0 -44
  186. package/dist/commands/graph-visualize.js.map +0 -1
  187. package/dist/commands/hooks-constants.d.ts +0 -2
  188. package/dist/commands/hooks-constants.d.ts.map +0 -1
  189. package/dist/commands/hooks-constants.js +0 -2
  190. package/dist/commands/hooks-constants.js.map +0 -1
  191. package/dist/commands/hooks.d.ts +0 -28
  192. package/dist/commands/hooks.d.ts.map +0 -1
  193. package/dist/commands/hooks.js +0 -187
  194. package/dist/commands/hooks.js.map +0 -1
  195. package/dist/commands/index.d.ts +0 -22
  196. package/dist/commands/index.d.ts.map +0 -1
  197. package/dist/commands/index.js +0 -472
  198. package/dist/commands/index.js.map +0 -1
  199. package/dist/commands/init.d.ts +0 -19
  200. package/dist/commands/init.d.ts.map +0 -1
  201. package/dist/commands/init.js +0 -210
  202. package/dist/commands/init.js.map +0 -1
  203. package/dist/commands/lang-queue.d.ts +0 -28
  204. package/dist/commands/lang-queue.d.ts.map +0 -1
  205. package/dist/commands/lang-queue.js +0 -49
  206. package/dist/commands/lang-queue.js.map +0 -1
  207. package/dist/commands/lang.d.ts +0 -16
  208. package/dist/commands/lang.d.ts.map +0 -1
  209. package/dist/commands/lang.js +0 -69
  210. package/dist/commands/lang.js.map +0 -1
  211. package/dist/commands/prototype.d.ts +0 -66
  212. package/dist/commands/prototype.d.ts.map +0 -1
  213. package/dist/commands/prototype.js +0 -370
  214. package/dist/commands/prototype.js.map +0 -1
  215. package/dist/commands/setup.d.ts +0 -26
  216. package/dist/commands/setup.d.ts.map +0 -1
  217. package/dist/commands/setup.js +0 -259
  218. package/dist/commands/setup.js.map +0 -1
  219. package/dist/commands/sync-cursor.d.ts +0 -10
  220. package/dist/commands/sync-cursor.d.ts.map +0 -1
  221. package/dist/commands/sync-cursor.js +0 -18
  222. package/dist/commands/sync-cursor.js.map +0 -1
  223. package/dist/commands/template-regen.d.ts +0 -24
  224. package/dist/commands/template-regen.d.ts.map +0 -1
  225. package/dist/commands/template-regen.js +0 -240
  226. package/dist/commands/template-regen.js.map +0 -1
  227. package/dist/commands/template.d.ts +0 -3
  228. package/dist/commands/template.d.ts.map +0 -1
  229. package/dist/commands/template.js +0 -1285
  230. package/dist/commands/template.js.map +0 -1
  231. package/dist/commands/validate.d.ts +0 -10
  232. package/dist/commands/validate.d.ts.map +0 -1
  233. package/dist/commands/validate.js +0 -89
  234. package/dist/commands/validate.js.map +0 -1
  235. package/dist/comments/anchor.d.ts +0 -16
  236. package/dist/comments/anchor.d.ts.map +0 -1
  237. package/dist/comments/anchor.js +0 -59
  238. package/dist/comments/anchor.js.map +0 -1
  239. package/dist/comments/inbox.d.ts +0 -82
  240. package/dist/comments/inbox.d.ts.map +0 -1
  241. package/dist/comments/inbox.js +0 -179
  242. package/dist/comments/inbox.js.map +0 -1
  243. package/dist/comments/paths.d.ts +0 -12
  244. package/dist/comments/paths.d.ts.map +0 -1
  245. package/dist/comments/paths.js +0 -54
  246. package/dist/comments/paths.js.map +0 -1
  247. package/dist/comments/plan.d.ts +0 -20
  248. package/dist/comments/plan.d.ts.map +0 -1
  249. package/dist/comments/plan.js +0 -62
  250. package/dist/comments/plan.js.map +0 -1
  251. package/dist/comments/storage.d.ts +0 -30
  252. package/dist/comments/storage.d.ts.map +0 -1
  253. package/dist/comments/storage.js +0 -272
  254. package/dist/comments/storage.js.map +0 -1
  255. package/dist/comments/types.d.ts +0 -54
  256. package/dist/comments/types.d.ts.map +0 -1
  257. package/dist/comments/types.js +0 -2
  258. package/dist/comments/types.js.map +0 -1
  259. package/dist/config/load.d.ts +0 -47
  260. package/dist/config/load.d.ts.map +0 -1
  261. package/dist/config/load.js +0 -148
  262. package/dist/config/load.js.map +0 -1
  263. package/dist/config/types.d.ts +0 -56
  264. package/dist/config/types.d.ts.map +0 -1
  265. package/dist/config/types.js +0 -2
  266. package/dist/config/types.js.map +0 -1
  267. package/dist/core/adopt/apply.d.ts +0 -15
  268. package/dist/core/adopt/apply.d.ts.map +0 -1
  269. package/dist/core/adopt/apply.js +0 -127
  270. package/dist/core/adopt/apply.js.map +0 -1
  271. package/dist/core/adopt/bootstrap.d.ts +0 -16
  272. package/dist/core/adopt/bootstrap.d.ts.map +0 -1
  273. package/dist/core/adopt/bootstrap.js +0 -195
  274. package/dist/core/adopt/bootstrap.js.map +0 -1
  275. package/dist/core/adopt/classify.d.ts +0 -22
  276. package/dist/core/adopt/classify.d.ts.map +0 -1
  277. package/dist/core/adopt/classify.js +0 -295
  278. package/dist/core/adopt/classify.js.map +0 -1
  279. package/dist/core/adopt/paths.d.ts +0 -10
  280. package/dist/core/adopt/paths.d.ts.map +0 -1
  281. package/dist/core/adopt/paths.js +0 -16
  282. package/dist/core/adopt/paths.js.map +0 -1
  283. package/dist/core/adopt/plan.d.ts +0 -10
  284. package/dist/core/adopt/plan.d.ts.map +0 -1
  285. package/dist/core/adopt/plan.js +0 -269
  286. package/dist/core/adopt/plan.js.map +0 -1
  287. package/dist/core/adopt/scan.d.ts +0 -5
  288. package/dist/core/adopt/scan.d.ts.map +0 -1
  289. package/dist/core/adopt/scan.js +0 -169
  290. package/dist/core/adopt/scan.js.map +0 -1
  291. package/dist/core/adopt/setup.d.ts +0 -7
  292. package/dist/core/adopt/setup.d.ts.map +0 -1
  293. package/dist/core/adopt/setup.js +0 -64
  294. package/dist/core/adopt/setup.js.map +0 -1
  295. package/dist/core/adopt/tasks.d.ts +0 -9
  296. package/dist/core/adopt/tasks.d.ts.map +0 -1
  297. package/dist/core/adopt/tasks.js +0 -153
  298. package/dist/core/adopt/tasks.js.map +0 -1
  299. package/dist/core/adopt/types.d.ts +0 -75
  300. package/dist/core/adopt/types.d.ts.map +0 -1
  301. package/dist/core/adopt/types.js +0 -2
  302. package/dist/core/adopt/types.js.map +0 -1
  303. package/dist/core/adopt/validate.d.ts +0 -20
  304. package/dist/core/adopt/validate.d.ts.map +0 -1
  305. package/dist/core/adopt/validate.js +0 -129
  306. package/dist/core/adopt/validate.js.map +0 -1
  307. package/dist/core/docops/dual-write.d.ts +0 -12
  308. package/dist/core/docops/dual-write.d.ts.map +0 -1
  309. package/dist/core/docops/dual-write.js +0 -44
  310. package/dist/core/docops/dual-write.js.map +0 -1
  311. package/dist/core/engine/local-adapter.d.ts +0 -3
  312. package/dist/core/engine/local-adapter.d.ts.map +0 -1
  313. package/dist/core/engine/local-adapter.js +0 -18
  314. package/dist/core/engine/local-adapter.js.map +0 -1
  315. package/dist/core/graph/rules/default-impact.json +0 -24
  316. package/dist/core/operations/adopt-gates.d.ts +0 -19
  317. package/dist/core/operations/adopt-gates.d.ts.map +0 -1
  318. package/dist/core/operations/adopt-gates.js +0 -71
  319. package/dist/core/operations/adopt-gates.js.map +0 -1
  320. package/dist/core/operations/adopt-plan.d.ts +0 -15
  321. package/dist/core/operations/adopt-plan.d.ts.map +0 -1
  322. package/dist/core/operations/adopt-plan.js +0 -24
  323. package/dist/core/operations/adopt-plan.js.map +0 -1
  324. package/dist/core/operations/adopt.d.ts +0 -11
  325. package/dist/core/operations/adopt.d.ts.map +0 -1
  326. package/dist/core/operations/adopt.js +0 -150
  327. package/dist/core/operations/adopt.js.map +0 -1
  328. package/dist/core/operations/analyze.d.ts +0 -12
  329. package/dist/core/operations/analyze.d.ts.map +0 -1
  330. package/dist/core/operations/analyze.js +0 -53
  331. package/dist/core/operations/analyze.js.map +0 -1
  332. package/dist/core/prototype/spa-route-fallbacks.d.ts +0 -21
  333. package/dist/core/prototype/spa-route-fallbacks.d.ts.map +0 -1
  334. package/dist/core/prototype/spa-route-fallbacks.js +0 -93
  335. package/dist/core/prototype/spa-route-fallbacks.js.map +0 -1
  336. package/dist/graph/InMemoryGraph.d.ts +0 -2
  337. package/dist/graph/InMemoryGraph.d.ts.map +0 -1
  338. package/dist/graph/InMemoryGraph.js +0 -2
  339. package/dist/graph/InMemoryGraph.js.map +0 -1
  340. package/dist/graph/bundles.d.ts +0 -32
  341. package/dist/graph/bundles.d.ts.map +0 -1
  342. package/dist/graph/bundles.js +0 -109
  343. package/dist/graph/bundles.js.map +0 -1
  344. package/dist/graph/defaults.d.ts +0 -23
  345. package/dist/graph/defaults.d.ts.map +0 -1
  346. package/dist/graph/defaults.js +0 -25
  347. package/dist/graph/defaults.js.map +0 -1
  348. package/dist/graph/detail-sections.d.ts +0 -28
  349. package/dist/graph/detail-sections.d.ts.map +0 -1
  350. package/dist/graph/detail-sections.js +0 -220
  351. package/dist/graph/detail-sections.js.map +0 -1
  352. package/dist/graph/doc-extract.d.ts +0 -84
  353. package/dist/graph/doc-extract.d.ts.map +0 -1
  354. package/dist/graph/doc-extract.js +0 -821
  355. package/dist/graph/doc-extract.js.map +0 -1
  356. package/dist/graph/impact.d.ts +0 -5
  357. package/dist/graph/impact.d.ts.map +0 -1
  358. package/dist/graph/impact.js +0 -7
  359. package/dist/graph/impact.js.map +0 -1
  360. package/dist/graph/knowledge.d.ts +0 -11
  361. package/dist/graph/knowledge.d.ts.map +0 -1
  362. package/dist/graph/knowledge.js +0 -62
  363. package/dist/graph/knowledge.js.map +0 -1
  364. package/dist/graph/layer-audit.d.ts +0 -5
  365. package/dist/graph/layer-audit.d.ts.map +0 -1
  366. package/dist/graph/layer-audit.js +0 -29
  367. package/dist/graph/layer-audit.js.map +0 -1
  368. package/dist/graph/load.d.ts +0 -4
  369. package/dist/graph/load.d.ts.map +0 -1
  370. package/dist/graph/load.js +0 -12
  371. package/dist/graph/load.js.map +0 -1
  372. package/dist/graph/loadGraph.d.ts +0 -3
  373. package/dist/graph/loadGraph.d.ts.map +0 -1
  374. package/dist/graph/loadGraph.js +0 -7
  375. package/dist/graph/loadGraph.js.map +0 -1
  376. package/dist/graph/merge.d.ts +0 -27
  377. package/dist/graph/merge.d.ts.map +0 -1
  378. package/dist/graph/merge.js +0 -239
  379. package/dist/graph/merge.js.map +0 -1
  380. package/dist/graph/path-target-edges.d.ts +0 -2
  381. package/dist/graph/path-target-edges.d.ts.map +0 -1
  382. package/dist/graph/path-target-edges.js +0 -2
  383. package/dist/graph/path-target-edges.js.map +0 -1
  384. package/dist/graph/provenance.d.ts +0 -19
  385. package/dist/graph/provenance.d.ts.map +0 -1
  386. package/dist/graph/provenance.js +0 -199
  387. package/dist/graph/provenance.js.map +0 -1
  388. package/dist/graph/query.d.ts +0 -3
  389. package/dist/graph/query.d.ts.map +0 -1
  390. package/dist/graph/query.js +0 -2
  391. package/dist/graph/query.js.map +0 -1
  392. package/dist/graph/resolve.d.ts +0 -15
  393. package/dist/graph/resolve.d.ts.map +0 -1
  394. package/dist/graph/resolve.js +0 -117
  395. package/dist/graph/resolve.js.map +0 -1
  396. package/dist/graph/source-refs.d.ts +0 -2
  397. package/dist/graph/source-refs.d.ts.map +0 -1
  398. package/dist/graph/source-refs.js +0 -30
  399. package/dist/graph/source-refs.js.map +0 -1
  400. package/dist/graph/translation.d.ts +0 -14
  401. package/dist/graph/translation.d.ts.map +0 -1
  402. package/dist/graph/translation.js +0 -65
  403. package/dist/graph/translation.js.map +0 -1
  404. package/dist/index/doc-semantics.d.ts +0 -14
  405. package/dist/index/doc-semantics.d.ts.map +0 -1
  406. package/dist/index/doc-semantics.js +0 -101
  407. package/dist/index/doc-semantics.js.map +0 -1
  408. package/dist/index/docs-build.d.ts +0 -40
  409. package/dist/index/docs-build.d.ts.map +0 -1
  410. package/dist/index/docs-build.js +0 -136
  411. package/dist/index/docs-build.js.map +0 -1
  412. package/dist/index/docs-config.d.ts +0 -19
  413. package/dist/index/docs-config.d.ts.map +0 -1
  414. package/dist/index/docs-config.js +0 -5
  415. package/dist/index/docs-config.js.map +0 -1
  416. package/dist/interfaces/cli/format/adopt.d.ts +0 -23
  417. package/dist/interfaces/cli/format/adopt.d.ts.map +0 -1
  418. package/dist/interfaces/cli/format/adopt.js +0 -89
  419. package/dist/interfaces/cli/format/adopt.js.map +0 -1
  420. package/dist/interfaces/mcp/tools/adopt.d.ts +0 -22
  421. package/dist/interfaces/mcp/tools/adopt.d.ts.map +0 -1
  422. package/dist/interfaces/mcp/tools/adopt.js +0 -55
  423. package/dist/interfaces/mcp/tools/adopt.js.map +0 -1
  424. package/dist/lang/diff.d.ts +0 -12
  425. package/dist/lang/diff.d.ts.map +0 -1
  426. package/dist/lang/diff.js +0 -71
  427. package/dist/lang/diff.js.map +0 -1
  428. package/dist/lang/paths.d.ts +0 -16
  429. package/dist/lang/paths.d.ts.map +0 -1
  430. package/dist/lang/paths.js +0 -32
  431. package/dist/lang/paths.js.map +0 -1
  432. package/dist/lang/queue-layout.d.ts +0 -11
  433. package/dist/lang/queue-layout.d.ts.map +0 -1
  434. package/dist/lang/queue-layout.js +0 -56
  435. package/dist/lang/queue-layout.js.map +0 -1
  436. package/dist/lang/queue-store.d.ts +0 -23
  437. package/dist/lang/queue-store.d.ts.map +0 -1
  438. package/dist/lang/queue-store.js +0 -285
  439. package/dist/lang/queue-store.js.map +0 -1
  440. package/dist/lang/queue-types.d.ts +0 -122
  441. package/dist/lang/queue-types.d.ts.map +0 -1
  442. package/dist/lang/queue-types.js +0 -2
  443. package/dist/lang/queue-types.js.map +0 -1
  444. package/dist/lang/queue.d.ts +0 -17
  445. package/dist/lang/queue.d.ts.map +0 -1
  446. package/dist/lang/queue.js +0 -362
  447. package/dist/lang/queue.js.map +0 -1
  448. package/dist/lang/sections.d.ts +0 -26
  449. package/dist/lang/sections.d.ts.map +0 -1
  450. package/dist/lang/sections.js +0 -85
  451. package/dist/lang/sections.js.map +0 -1
  452. package/dist/markdown/parse.d.ts +0 -25
  453. package/dist/markdown/parse.d.ts.map +0 -1
  454. package/dist/markdown/parse.js +0 -100
  455. package/dist/markdown/parse.js.map +0 -1
  456. package/dist/prototype/build-base-path.d.ts +0 -11
  457. package/dist/prototype/build-base-path.d.ts.map +0 -1
  458. package/dist/prototype/build-base-path.js +0 -84
  459. package/dist/prototype/build-base-path.js.map +0 -1
  460. package/dist/prototype/build-manifest.d.ts +0 -21
  461. package/dist/prototype/build-manifest.d.ts.map +0 -1
  462. package/dist/prototype/build-manifest.js +0 -171
  463. package/dist/prototype/build-manifest.js.map +0 -1
  464. package/dist/prototype/config.d.ts +0 -21
  465. package/dist/prototype/config.d.ts.map +0 -1
  466. package/dist/prototype/config.js +0 -131
  467. package/dist/prototype/config.js.map +0 -1
  468. package/dist/prototype/deploy-path.d.ts +0 -9
  469. package/dist/prototype/deploy-path.d.ts.map +0 -1
  470. package/dist/prototype/deploy-path.js +0 -21
  471. package/dist/prototype/deploy-path.js.map +0 -1
  472. package/dist/prototype/htpasswd.d.ts +0 -8
  473. package/dist/prototype/htpasswd.d.ts.map +0 -1
  474. package/dist/prototype/htpasswd.js +0 -36
  475. package/dist/prototype/htpasswd.js.map +0 -1
  476. package/dist/prototype/nginx-config.d.ts +0 -16
  477. package/dist/prototype/nginx-config.d.ts.map +0 -1
  478. package/dist/prototype/nginx-config.js +0 -39
  479. package/dist/prototype/nginx-config.js.map +0 -1
  480. package/dist/prototype/parse-screen-index.d.ts +0 -10
  481. package/dist/prototype/parse-screen-index.d.ts.map +0 -1
  482. package/dist/prototype/parse-screen-index.js +0 -109
  483. package/dist/prototype/parse-screen-index.js.map +0 -1
  484. package/dist/prototype/preview-uri.d.ts +0 -8
  485. package/dist/prototype/preview-uri.d.ts.map +0 -1
  486. package/dist/prototype/preview-uri.js +0 -35
  487. package/dist/prototype/preview-uri.js.map +0 -1
  488. package/dist/prototype/relative-assets.d.ts +0 -9
  489. package/dist/prototype/relative-assets.d.ts.map +0 -1
  490. package/dist/prototype/relative-assets.js +0 -23
  491. package/dist/prototype/relative-assets.js.map +0 -1
  492. package/dist/prototype/resolve-default-screen.d.ts +0 -17
  493. package/dist/prototype/resolve-default-screen.d.ts.map +0 -1
  494. package/dist/prototype/resolve-default-screen.js +0 -31
  495. package/dist/prototype/resolve-default-screen.js.map +0 -1
  496. package/dist/prototype/rewrite-build-assets.d.ts +0 -8
  497. package/dist/prototype/rewrite-build-assets.d.ts.map +0 -1
  498. package/dist/prototype/rewrite-build-assets.js +0 -40
  499. package/dist/prototype/rewrite-build-assets.js.map +0 -1
  500. package/dist/prototype/route-defaults.d.ts +0 -43
  501. package/dist/prototype/route-defaults.d.ts.map +0 -1
  502. package/dist/prototype/route-defaults.js +0 -50
  503. package/dist/prototype/route-defaults.js.map +0 -1
  504. package/dist/prototype/screen-doc-paths.d.ts +0 -15
  505. package/dist/prototype/screen-doc-paths.d.ts.map +0 -1
  506. package/dist/prototype/screen-doc-paths.js +0 -38
  507. package/dist/prototype/screen-doc-paths.js.map +0 -1
  508. package/dist/prototype/spa-route-fallbacks.d.ts +0 -21
  509. package/dist/prototype/spa-route-fallbacks.d.ts.map +0 -1
  510. package/dist/prototype/spa-route-fallbacks.js +0 -93
  511. package/dist/prototype/spa-route-fallbacks.js.map +0 -1
  512. package/dist/prototype/theme-preview.d.ts +0 -17
  513. package/dist/prototype/theme-preview.d.ts.map +0 -1
  514. package/dist/prototype/theme-preview.js +0 -73
  515. package/dist/prototype/theme-preview.js.map +0 -1
  516. package/dist/prototype/themes.d.ts +0 -6
  517. package/dist/prototype/themes.d.ts.map +0 -1
  518. package/dist/prototype/themes.js +0 -55
  519. package/dist/prototype/themes.js.map +0 -1
  520. package/dist/prototype/types.d.ts +0 -160
  521. package/dist/prototype/types.d.ts.map +0 -1
  522. package/dist/prototype/types.js +0 -2
  523. package/dist/prototype/types.js.map +0 -1
  524. package/dist/prototype/validate.d.ts +0 -16
  525. package/dist/prototype/validate.d.ts.map +0 -1
  526. package/dist/prototype/validate.js +0 -149
  527. package/dist/prototype/validate.js.map +0 -1
  528. package/dist/registry/build.d.ts +0 -5
  529. package/dist/registry/build.d.ts.map +0 -1
  530. package/dist/registry/build.js +0 -71
  531. package/dist/registry/build.js.map +0 -1
  532. package/dist/registry/slug.d.ts +0 -4
  533. package/dist/registry/slug.d.ts.map +0 -1
  534. package/dist/registry/slug.js +0 -16
  535. package/dist/registry/slug.js.map +0 -1
  536. package/dist/registry/structure-patch.d.ts +0 -6
  537. package/dist/registry/structure-patch.d.ts.map +0 -1
  538. package/dist/registry/structure-patch.js +0 -49
  539. package/dist/registry/structure-patch.js.map +0 -1
  540. package/dist/template/scan.d.ts +0 -21
  541. package/dist/template/scan.d.ts.map +0 -1
  542. package/dist/template/scan.js +0 -84
  543. package/dist/template/scan.js.map +0 -1
  544. package/dist/template/validate.d.ts +0 -10
  545. package/dist/template/validate.d.ts.map +0 -1
  546. package/dist/template/validate.js +0 -64
  547. package/dist/template/validate.js.map +0 -1
  548. package/dist/util/fs.d.ts +0 -6
  549. package/dist/util/fs.d.ts.map +0 -1
  550. package/dist/util/fs.js +0 -24
  551. package/dist/util/fs.js.map +0 -1
  552. package/dist/util/git-diff.d.ts +0 -16
  553. package/dist/util/git-diff.d.ts.map +0 -1
  554. package/dist/util/git-diff.js +0 -93
  555. package/dist/util/git-diff.js.map +0 -1
  556. package/dist/util/gitignore.d.ts +0 -9
  557. package/dist/util/gitignore.d.ts.map +0 -1
  558. package/dist/util/gitignore.js +0 -44
  559. package/dist/util/gitignore.js.map +0 -1
  560. package/dist/util/open-browser.d.ts +0 -3
  561. package/dist/util/open-browser.d.ts.map +0 -1
  562. package/dist/util/open-browser.js +0 -24
  563. package/dist/util/open-browser.js.map +0 -1
  564. package/dist/util/paths.d.ts +0 -16
  565. package/dist/util/paths.d.ts.map +0 -1
  566. package/dist/util/paths.js +0 -19
  567. package/dist/util/paths.js.map +0 -1
  568. package/dist/util/prompt.d.ts +0 -14
  569. package/dist/util/prompt.d.ts.map +0 -1
  570. package/dist/util/prompt.js +0 -65
  571. package/dist/util/prompt.js.map +0 -1
  572. package/dist/visualize/html.d.ts +0 -13
  573. package/dist/visualize/html.d.ts.map +0 -1
  574. package/dist/visualize/html.js +0 -766
  575. package/dist/visualize/html.js.map +0 -1
  576. package/dist/visualize/stats.d.ts +0 -8
  577. package/dist/visualize/stats.d.ts.map +0 -1
  578. package/dist/visualize/stats.js +0 -9
  579. package/dist/visualize/stats.js.map +0 -1
@@ -1,1285 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { copyFile, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
3
- import { join, resolve } from "node:path";
4
- import { findProjectRoot, loadDocflowConfig, resolveFromRoot, loadDocumentsManifest, loadBasicDesignListManifest, } from "../config/load.js";
5
- import { readJson, writeJson, pathExists, copyTree } from "../util/fs.js";
6
- import { buildSectionRegistry } from "../registry/build.js";
7
- import { bootstrapFromRegistry } from "./bootstrap.js";
8
- import { scanTemplateFolder } from "../template/scan.js";
9
- import { validatePackManifest } from "../template/validate.js";
10
- import { runTemplateRegen } from "./template-regen.js";
11
- // ---------------------------------------------------------------------------
12
- // Helpers
13
- // ---------------------------------------------------------------------------
14
- async function loadConfigAndRoot(cwd) {
15
- const root = cwd ?? findProjectRoot();
16
- const { config, configFile } = await loadDocflowConfig(root);
17
- return { root, config, configFile };
18
- }
19
- async function saveConfig(configFile, config) {
20
- await writeJson(configFile, config);
21
- }
22
- async function rebuildRegistryAndGraph(root, config) {
23
- const p = config.paths;
24
- const registryPath = resolveFromRoot(root, p.registry);
25
- const graphPath = resolveFromRoot(root, p.graph);
26
- const registry = await buildSectionRegistry(root);
27
- await writeJson(registryPath, registry);
28
- const graph = bootstrapFromRegistry(registry);
29
- await writeJson(graphPath, graph.toTraceabilityGraph());
30
- const totalSections = registry.documents.reduce((n, d) => n + d.sections.length, 0);
31
- const tg = graph.toTraceabilityGraph();
32
- return {
33
- documents: registry.documents.length,
34
- sections: totalSections,
35
- graphNodes: graph.nodesById.size,
36
- graphEdges: tg.edges.length,
37
- documentIds: tg.nodes.filter((n) => n.type === "document").map((n) => n.id),
38
- };
39
- }
40
- async function listInstalledPackNames(root) {
41
- const packsDir = join(root, ".ai-spector", "packs");
42
- if (!(await pathExists(packsDir)))
43
- return [];
44
- try {
45
- const entries = await readdir(packsDir, { withFileTypes: true });
46
- return entries
47
- .filter((e) => e.isDirectory() && e.name !== ".staging")
48
- .map((e) => e.name);
49
- }
50
- catch {
51
- return [];
52
- }
53
- }
54
- // ---------------------------------------------------------------------------
55
- // template list
56
- // ---------------------------------------------------------------------------
57
- async function runTemplateList(opts) {
58
- const { root, config } = await loadConfigAndRoot(opts.cwd);
59
- const active = config.packs?.active;
60
- const installed = await listInstalledPackNames(root);
61
- console.log("Template packs:");
62
- // builtin entry
63
- const builtinActive = !active || active === "builtin";
64
- const builtinMarker = builtinActive ? "●" : "○";
65
- const builtinStatus = builtinActive ? "(active)" : "(default — used when no custom pack is active)";
66
- console.log(` ${builtinMarker} builtin ${builtinStatus}`);
67
- // installed custom packs
68
- for (const name of installed) {
69
- const isActive = active === name;
70
- const marker = isActive ? "●" : "○";
71
- const status = isActive ? "(active)" : "(inactive)";
72
- let description = "";
73
- try {
74
- const manifestPath = join(root, ".ai-spector", "packs", name, "manifest.json");
75
- const manifest = await readJson(manifestPath);
76
- description = manifest.description ? ` ${manifest.description}` : "";
77
- }
78
- catch {
79
- // ignore
80
- }
81
- console.log(` ${marker} ${name.padEnd(16)}${status}${description}`);
82
- }
83
- }
84
- // ---------------------------------------------------------------------------
85
- // DAG generation from pack manifest
86
- // ---------------------------------------------------------------------------
87
- /**
88
- * Derive a `dag.srs.json` + `dag.srs.graph-seeds.json` pair from a pack manifest.
89
- *
90
- * - Non-perDomain documents → flat DAG nodes (no dependsOn; AI refines ordering).
91
- * - perDomain documents → DAG nodes with `mode: "perDomainBreakout"` and the
92
- * `perDomainKey` field so the generate skill knows to produce one file per domain item.
93
- */
94
- function buildDagFromManifest(manifest) {
95
- const packSlug = manifest.packName.replace(/[^a-z0-9]/gi, "-").toLowerCase();
96
- const dagNodes = [];
97
- const seedsMap = {};
98
- const primaryDagIds = [];
99
- // Pass 1: primary (non-perDomain) documents
100
- for (const doc of manifest.documents) {
101
- if (doc.perDomain)
102
- continue;
103
- const docSlug = doc.documentId.replace(/^doc\.[^.]+\./, "").replace(/\./g, "-");
104
- const dagId = `${packSlug}.${docSlug}`;
105
- const output = doc.output ?? doc.outputPattern ?? `${docSlug}.md`;
106
- dagNodes.push({ id: dagId, template: doc.template, output, dependsOn: [] });
107
- seedsMap[dagId] = doc.documentId;
108
- primaryDagIds.push(dagId);
109
- }
110
- // Pass 2: perDomain breakout documents — one DAG node each, depends on primary docs
111
- for (const doc of manifest.documents) {
112
- if (!doc.perDomain)
113
- continue;
114
- const docSlug = doc.documentId.replace(/^doc\.[^.]+\./, "").replace(/\./g, "-");
115
- const dagId = `${packSlug}.${docSlug}-breakout`;
116
- const outputPattern = doc.outputPattern ?? doc.output ?? `${docSlug}/{id}.md`;
117
- dagNodes.push({
118
- id: dagId,
119
- template: doc.template,
120
- outputPattern,
121
- dependsOn: primaryDagIds,
122
- mode: "perDomainBreakout",
123
- perDomainKey: doc.perDomain,
124
- });
125
- seedsMap[dagId] = doc.documentId;
126
- }
127
- const dag = { version: 1, root: "docs/srs", nodes: dagNodes };
128
- // perDomain section: maps domain keys to graph node type + template doc id
129
- // graphNodeType is the NodeType enum value in the graph (e.g. "requirement", "useCase")
130
- const perDomainSeeds = {};
131
- if (manifest.perDomainTemplates) {
132
- for (const [domain, templateDocId] of Object.entries(manifest.perDomainTemplates)) {
133
- if (!templateDocId)
134
- continue;
135
- perDomainSeeds[domain] = {
136
- graphNodeType: domain,
137
- templateDocId,
138
- seedFromDomainId: true,
139
- };
140
- }
141
- }
142
- const seeds = {
143
- version: 1,
144
- description: `Map dag.srs.json node ids to graph document ids for pack "${manifest.packName}"`,
145
- seeds: seedsMap,
146
- perDomain: perDomainSeeds,
147
- };
148
- return { dag, seeds };
149
- }
150
- /**
151
- * Write a human+AI-readable generate-hints.md into the pack directory.
152
- * Describes the generation waves and breakout templates so the generate skill
153
- * can drive the correct output without reading the manifest directly.
154
- */
155
- async function writeGenerateHints(packDir, manifest) {
156
- const primaryDocs = manifest.documents.filter((d) => !d.perDomain);
157
- const breakoutDocs = manifest.documents.filter((d) => d.perDomain);
158
- const lines = [
159
- `# Generate hints for pack: ${manifest.packName}`,
160
- "",
161
- `> Auto-generated by \`template install\`. Update manually if generation order changes.`,
162
- "",
163
- "## Wave 0 — Primary documents",
164
- "",
165
- "Generate these first (no inter-document dependencies assumed):",
166
- "",
167
- ];
168
- for (const doc of primaryDocs) {
169
- const output = doc.output ?? doc.outputPattern ?? "(see manifest)";
170
- lines.push(`- **${doc.documentId}** → \`${output}\``);
171
- lines.push(` Template: \`${doc.template}\``);
172
- }
173
- if (breakoutDocs.length > 0) {
174
- lines.push("", "## Wave 1 — Per-domain breakout files", "", "**Start only after Wave 0 is complete and `npx ai-spector index` has run.**", "", "### Required per-item workflow", "", "Generate one item at a time — do NOT script or loop over knowledge.json:", "", "```", "1. npx ai-spector graph query <itemId> --direction both --depth 4 --edges CONTEXT --json", "2. Read projectionPaths — these are the only allowed source files", "3. Load the breakout template (listed below)", "4. Write output file with specific, verifiable content from graph context", "5. Repeat for next item", "```", "", "After all items: batch merge `rendersTo` edges → `graph validate` → `index`.", "", "For 10+ items: use sub-agents (3–5 items each). Load `generate-workflow.md` → `context-management.md`.", "", "⛔ **Anti-pattern:** do not run a script over `knowledge.json` to stamp all files at once.", "Script output passes validate/index but contains boilerplate, not real domain content.", "See `.cursor/skills/ai-spector/references/generate-graph.md §F` for the rule.", "");
175
- for (const doc of breakoutDocs) {
176
- const output = doc.outputPattern ?? doc.output ?? "(see manifest)";
177
- lines.push(`### ${doc.perDomain} — \`${doc.documentId}\``);
178
- lines.push("");
179
- lines.push(`- Output pattern: \`${output}\``);
180
- lines.push(`- Template: \`.ai-spector/packs/${manifest.packName}/templates/${doc.template}\``);
181
- lines.push(`- Graph node type: \`${doc.perDomain}\``);
182
- lines.push("");
183
- lines.push("Get the item list:");
184
- lines.push("```bash");
185
- lines.push(`npx ai-spector graph query <any-wave0-documentId> --direction both --depth 4 --json`);
186
- lines.push(`# filter: nodes where type === "${doc.perDomain}"`);
187
- lines.push(`# or: npx ai-spector graph query ${doc.documentId} --json`);
188
- lines.push("```");
189
- lines.push("");
190
- }
191
- if (manifest.defaultListedIn) {
192
- lines.push("### Breakout list anchors", "");
193
- for (const [domain, sectionId] of Object.entries(manifest.defaultListedIn)) {
194
- lines.push(`- \`${domain}\` items are listed in: \`${sectionId}\``);
195
- }
196
- lines.push("");
197
- }
198
- }
199
- else {
200
- lines.push("", "> This pack has no per-domain breakout templates.");
201
- }
202
- lines.push("", "## When to pause and ask the user", "", "Stop generating and ask if:", "", "- A `{placeholder}` in a template has no matching value in the graph query result", "- The item list for a breakout domain returns 0 results or ambiguous node types", "- Two output paths could satisfy the same `outputPattern`", "- A Wave 0 document already exists and it is unclear whether to overwrite or append", "- `graph validate` fails after writing and the error is not self-explanatory", "", "⛔ **Do NOT guess. A wrong file written silently is harder to fix than a question asked upfront.**", "", "See `context-map.json` in this directory for the expected source of each `{placeholder}`.", "", "## Reference", "", `- Pack manifest: \`.ai-spector/packs/${manifest.packName}/manifest.json\``, `- Context map: \`.ai-spector/packs/${manifest.packName}/context-map.json\``, `- Inspect pack: \`npx ai-spector template inspect ${manifest.packName}\``, `- Active graph seeds: see \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\``);
203
- await writeFile(join(packDir, "generate-hints.md"), lines.join("\n") + "\n", "utf8");
204
- }
205
- /**
206
- * Write a context-map.json into the pack directory.
207
- *
208
- * Lists every {placeholder} found across all templates and the suggested graph
209
- * field path to resolve it from. Unknown placeholders get `"source": "TODO"` so
210
- * the user (or AI) can fill them in before generating.
211
- */
212
- async function writeContextMap(packDir, manifest, scanResult) {
213
- // Collect all unique placeholders across all template files
214
- const allPlaceholders = new Set();
215
- if (scanResult) {
216
- for (const f of scanResult.files) {
217
- for (const p of f.placeholders) {
218
- allPlaceholders.add(p);
219
- }
220
- }
221
- }
222
- // Also collect from manifest-level metadata if present
223
- for (const doc of manifest.documents) {
224
- for (const p of [doc.output ?? "", doc.outputPattern ?? ""]) {
225
- const m = p.matchAll(/\{([a-zA-Z][a-zA-Z0-9_-]*)\}/g);
226
- for (const [, name] of m)
227
- allPlaceholders.add(`{${name}}`);
228
- }
229
- }
230
- // Build a mapping with best-guess sources
231
- const KNOWN_SOURCES = {
232
- "{projectName}": "graph.metadata.projectName or config.projectName",
233
- "{project}": "graph.metadata.projectName or config.projectName",
234
- "{domain}": "graph node id (perDomain item)",
235
- "{id}": "graph node id",
236
- "{title}": "graph node title or heading",
237
- "{feature}": "graph node id (feature type)",
238
- "{module}": "graph node id (module type)",
239
- "{screen}": "graph node id (screen type)",
240
- "{date}": "new Date().toISOString().slice(0, 10)",
241
- "{version}": "config.version or package.json version",
242
- };
243
- const entries = {};
244
- for (const placeholder of [...allPlaceholders].sort()) {
245
- const known = KNOWN_SOURCES[placeholder];
246
- entries[placeholder] = {
247
- source: known ?? "TODO",
248
- note: known
249
- ? "auto-resolved"
250
- : "fill in before generating — ask user if unclear",
251
- };
252
- }
253
- const map = {
254
- _description: "Maps every {placeholder} in this pack's templates to its graph/config source. " +
255
- "Entries marked TODO must be resolved before generation.",
256
- packName: manifest.packName,
257
- generatedAt: new Date().toISOString(),
258
- placeholders: entries,
259
- };
260
- await writeFile(join(packDir, "context-map.json"), JSON.stringify(map, null, 2) + "\n", "utf8");
261
- }
262
- /**
263
- * Write a dedicated Cursor + Claude generate skill for the installed pack.
264
- *
265
- * Priority: if the AI wrote generate-skill.md to staging during the import workflow,
266
- * use it directly (it's tailored to the specific template). Otherwise fall back to
267
- * auto-generating a structural skeleton from the manifest.
268
- */
269
- async function writePackGenerateSkill(root, manifest, stagedSkillPath) {
270
- const name = manifest.packName;
271
- const slug = name.replace(/[^a-z0-9]/gi, "-").toLowerCase();
272
- // If the AI wrote a tailored skill during the import workflow, use it directly
273
- if (stagedSkillPath && existsSync(stagedSkillPath)) {
274
- const tailoredContent = await readFile(stagedSkillPath, "utf8");
275
- const cursorSkillDir = join(root, ".cursor", "skills", `ai-spector-generate-${slug}`);
276
- await mkdir(cursorSkillDir, { recursive: true });
277
- await writeFile(join(cursorSkillDir, "SKILL.md"), tailoredContent, "utf8");
278
- // Derive a minimal Claude skill from the tailored content (strip frontmatter + reformat)
279
- const claudeContent = [
280
- `---`,
281
- `name: ai-spector-generate-${slug}`,
282
- `description: "Generates documents for the ${name} template pack. Use the pack-specific Cursor skill for full details."`,
283
- `---`,
284
- ``,
285
- `# AI Spector — Generate (${name} pack)`,
286
- ``,
287
- `## When to use`,
288
- ``,
289
- `- Any request to generate, write, or update documents for pack \`${name}\``,
290
- ``,
291
- `## Step 0 — Load pack context`,
292
- ``,
293
- `Read these files before generating:`,
294
- `1. \`.ai-spector/packs/${name}/generate-hints.md\``,
295
- `2. \`.ai-spector/.docflow/config/dag.srs.json\``,
296
- `3. \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\``,
297
- ``,
298
- `Then follow the wave structure from \`generate-hints.md\`.`,
299
- ``,
300
- `## Checklist`,
301
- ``,
302
- `\`\`\``,
303
- `- [ ] Loaded generate-hints.md and DAG config`,
304
- `- [ ] graph validate passes before starting`,
305
- `- [ ] Wave 0 primary documents generated`,
306
- `- [ ] Wave 1 breakout files generated (if any)`,
307
- `- [ ] npx ai-spector index run after each wave`,
308
- `\`\`\``,
309
- ].join("\n");
310
- const claudeSkillDir = join(root, ".claude", "skills", `ai-spector-generate-${slug}`);
311
- await mkdir(claudeSkillDir, { recursive: true });
312
- await writeFile(join(claudeSkillDir, "skill.md"), claudeContent + "\n", "utf8");
313
- return;
314
- }
315
- // Fallback: auto-generate a structural skeleton from the manifest
316
- // Derive description from primary docs
317
- const primaryDocs = manifest.documents.filter((d) => !d.perDomain);
318
- const breakoutDocs = manifest.documents.filter((d) => d.perDomain);
319
- const primaryOutputs = primaryDocs
320
- .map((d) => d.output ?? d.outputPattern ?? d.template)
321
- .slice(0, 3)
322
- .join(", ");
323
- const breakoutNote = breakoutDocs.length > 0
324
- ? ` Plus ${breakoutDocs.length} breakout template(s): ${breakoutDocs.map((d) => d.perDomain).join(", ")}.`
325
- : "";
326
- // Infer docs/ path for `paths:` frontmatter
327
- const outputPaths = new Set();
328
- for (const doc of manifest.documents) {
329
- const p = (doc.output ?? doc.outputPattern ?? "docs/").split("/").slice(0, 2).join("/") + "/**";
330
- outputPaths.add(p);
331
- }
332
- const pathsYaml = [...outputPaths].map((p) => ` - "${p}"`).join("\n");
333
- const cursorSkillContent = [
334
- `---`,
335
- `name: ai-spector-generate-${slug}`,
336
- `description: >-`,
337
- ` Generates documents for the ${name} template pack. Use when the user asks to`,
338
- ` generate, write, or update documents produced by this pack. Outputs: ${primaryOutputs}.${breakoutNote}`,
339
- ` Active pack: ${name}.`,
340
- `paths:`,
341
- pathsYaml,
342
- `---`,
343
- ``,
344
- `# Generate — ${name} pack`,
345
- ``,
346
- `## Load at start (in order)`,
347
- `1. \`.ai-spector/packs/${name}/generate-hints.md\``,
348
- `2. \`.ai-spector/.docflow/config/dag.srs.json\``,
349
- `3. \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\``,
350
- `4. [\`generate-workflow.md\`](../ai-spector/references/generate-workflow.md)`,
351
- ``,
352
- `## Pack`,
353
- ``,
354
- `- Name: \`${name}\``,
355
- `- Templates: \`.ai-spector/packs/${name}/templates/\``,
356
- `- Manifest: \`.ai-spector/packs/${name}/manifest.json\``,
357
- `- Context map: \`.ai-spector/packs/${name}/context-map.json\` — placeholder → graph field`,
358
- ``,
359
- `## Before you start`,
360
- ``,
361
- `1. Read \`context-map.json\` — check every entry marked \`TODO\` and resolve it or ask the user.`,
362
- `2. Run \`npx ai-spector graph validate\` — fix any errors before writing files.`,
363
- ``,
364
- `## Workflow`,
365
- ``,
366
- `Follow the wave structure from \`generate-hints.md\`.`,
367
- ``,
368
- `**Wave 0 — Primary documents (exact table):**`,
369
- ``,
370
- `| documentId | template | output |`,
371
- `|---|---|---|`,
372
- ...primaryDocs.map((d) => `| \`${d.documentId}\` | \`${d.template}\` | \`${d.output ?? d.outputPattern ?? "(see manifest)"}\` |`),
373
- ``,
374
- `- Graph seed id: look up the \`documentId\` in \`dag.srs.graph-seeds.json\` to get the graph node id to query`,
375
- `- **Do NOT** use builtin \`doc.srs.*\` ids — they do not exist in this pack's graph`,
376
- ``,
377
- ...(breakoutDocs.length > 0
378
- ? [
379
- `**Wave 1 — Breakout files (${breakoutDocs.map((d) => d.perDomain).join(", ")}):**`,
380
- ``,
381
- `Start only after Wave 0 is complete and \`npx ai-spector index\` has run.`,
382
- ``,
383
- `**Required per-item workflow — one item at a time:**`,
384
- ``,
385
- `\`\`\``,
386
- `1. npx ai-spector graph query <itemId> --direction both --depth 4 --edges CONTEXT --json`,
387
- `2. Read projectionPaths — these are the only allowed source files`,
388
- `3. Write output file with specific, verifiable content from graph context`,
389
- `4. Repeat for next item`,
390
- `\`\`\``,
391
- ``,
392
- `After all items are written: batch merge rendersTo edges, then validate + index.`,
393
- ``,
394
- `⛔ **Do NOT generate breakout files via a script or loop over knowledge.json.**`,
395
- `Script-generated files pass validate/index but contain boilerplate, not real content.`,
396
- `See [\`generate-graph.md §F\`](../ai-spector/references/generate-graph.md) for the full rule.`,
397
- ``,
398
- `For 10+ items: use sub-agents (3–5 items each). Load context-management.md.`,
399
- ``,
400
- ]
401
- : []),
402
- `## Re-generation mode (source doc changed)`,
403
- ``,
404
- `When the user says "regenerate", "update stale docs", "source changed", or similar:`,
405
- ``,
406
- `1. Run: \`npx ai-spector template regen --json\``,
407
- `2. Read \`.ai-spector/packs/${name}/regen-plan.md\` — it lists exactly which files are stale and why`,
408
- `3. Regenerate ONLY the listed files — do NOT touch others`,
409
- `4. For each file: query the graph for the affected node context first`,
410
- ` \`npx ai-spector graph query <nodeId> --direction both --depth 4 --json\``,
411
- `5. Update gen-status.json entries for regenerated files`,
412
- `6. After all files: \`npx ai-spector index\` + \`npx ai-spector graph validate\``,
413
- ``,
414
- `⛔ Do NOT regenerate files that are NOT in the regen plan. Scope is everything.`,
415
- ``,
416
- `## After each breakout item — update gen-status.json`,
417
- ``,
418
- `After writing each breakout file, append an entry to \`.ai-spector/packs/${name}/gen-status.json\`:`,
419
- ``,
420
- `\`\`\`json`,
421
- `{`,
422
- ` "packName": "${name}",`,
423
- ` "updatedAt": "<ISO timestamp>",`,
424
- ` "items": [`,
425
- ` { "itemId": "<graphNodeId>", "outputFile": "<relative path>", "status": "done", "generatedAt": "<ISO>" },`,
426
- ` { "itemId": "<id>", "status": "blocked", "blockedReason": "<why you need human input>" }`,
427
- ` ]`,
428
- `}`,
429
- `\`\`\``,
430
- ``,
431
- `Status values: \`done\` | \`pending\` | \`blocked\`.`,
432
- `Set \`blocked\` + \`blockedReason\` when you cannot proceed — user can run \`npx ai-spector template status\` to see it.`,
433
- ``,
434
- `## After each wave`,
435
- ``,
436
- `\`\`\`bash`,
437
- `npx ai-spector graph validate`,
438
- `npx ai-spector index`,
439
- `\`\`\``,
440
- ``,
441
- `## When to pause and ask the user`,
442
- ``,
443
- `Stop and ask if:`,
444
- ``,
445
- `- A \`{placeholder}\` in a template has no matching value in the graph result`,
446
- `- The item list for a breakout domain returns 0 or ambiguous results`,
447
- `- Two output paths could satisfy the same \`outputPattern\``,
448
- `- A Wave 0 output file already exists and it is unclear whether to overwrite or append`,
449
- `- \`graph validate\` fails after writing and the error is not self-explanatory`,
450
- ``,
451
- `⛔ Do NOT guess. Wrong files written silently are harder to fix than a question asked upfront.`,
452
- ``,
453
- `## On CLI failure`,
454
- ``,
455
- `Load [\`cli-failures.md\`](../ai-spector/references/cli-failures.md).`,
456
- ``,
457
- `"generate ${name}", "write docs", "generate documents" → this skill.`,
458
- ].join("\n");
459
- const claudeSkillContent = [
460
- `---`,
461
- `name: ai-spector-generate-${slug}`,
462
- `description: "Generates documents for the ${name} template pack. Use when the user asks to generate, write, or update documents. Outputs: ${primaryOutputs}.${breakoutNote}"`,
463
- `---`,
464
- ``,
465
- `# AI Spector — Generate (${name} pack)`,
466
- ``,
467
- `## When to use`,
468
- ``,
469
- `- "generate ${name}", "write docs", "generate documents" when pack \`${name}\` is active`,
470
- ``,
471
- `## Step 0 — Load pack context`,
472
- ``,
473
- `Read these files before generating anything:`,
474
- `1. \`.ai-spector/packs/${name}/generate-hints.md\` — wave structure`,
475
- `2. \`.ai-spector/.docflow/config/dag.srs.json\` — DAG node order`,
476
- `3. \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\` — graph seed ids`,
477
- ``,
478
- `## Workflow`,
479
- ``,
480
- `Follow wave structure from \`generate-hints.md\`.`,
481
- ``,
482
- `\`\`\``,
483
- `1. Load generate-hints.md + DAG config`,
484
- `2. Wave 0: generate primary documents (use seed ids from dag.srs.graph-seeds.json)`,
485
- ...(breakoutDocs.length > 0
486
- ? [`3. Wave 1: generate breakout files (one per graph node of perDomainKey type)`]
487
- : []),
488
- `${breakoutDocs.length > 0 ? "4" : "3"}. After each wave: npx ai-spector index`,
489
- `${breakoutDocs.length > 0 ? "5" : "4"}. Final: npx ai-spector graph validate`,
490
- `\`\`\``,
491
- ``,
492
- `**Important:** Use graph seed ids from \`dag.srs.graph-seeds.json\`, NOT builtin \`doc.srs.*\` ids.`,
493
- ``,
494
- `Before generating: read \`context-map.json\` and resolve any entry marked \`TODO\` — ask the user if unclear.`,
495
- ``,
496
- `## When to pause and ask the user`,
497
- ``,
498
- `Stop and ask if:`,
499
- ``,
500
- `- A \`{placeholder}\` has no matching value in the graph result`,
501
- `- The breakout item list returns 0 or ambiguous results`,
502
- `- An output file already exists and it is unclear whether to overwrite`,
503
- `- \`graph validate\` fails and the error is not self-explanatory`,
504
- ``,
505
- `⛔ Do NOT guess. Ask instead.`,
506
- ``,
507
- `## Re-generation mode`,
508
- ``,
509
- `When user says "regenerate", "update stale docs", or "source changed":`,
510
- ``,
511
- `\`\`\``,
512
- `1. npx ai-spector template regen --json`,
513
- `2. Read regen-plan.md — regenerate ONLY listed files`,
514
- `3. Query graph context for each affected node before rewriting`,
515
- `4. Update gen-status.json`,
516
- `5. npx ai-spector index + graph validate`,
517
- `\`\`\``,
518
- ``,
519
- ...(breakoutDocs.length > 0
520
- ? [
521
- `## Tracking breakout progress (gen-status.json)`,
522
- ``,
523
- `After each breakout item, update \`.ai-spector/packs/${name}/gen-status.json\`:`,
524
- `- \`"status": "done"\` + \`outputFile\` + \`generatedAt\` when written successfully`,
525
- `- \`"status": "blocked"\` + \`blockedReason\` when you need human input`,
526
- ``,
527
- `User can run \`npx ai-spector template status\` to see what's done/blocked.`,
528
- ``,
529
- ]
530
- : []),
531
- `## Checklist`,
532
- ``,
533
- `\`\`\``,
534
- `- [ ] Loaded generate-hints.md and DAG config`,
535
- `- [ ] graph validate passes before starting`,
536
- `- [ ] Wave 0 primary documents generated`,
537
- ...(breakoutDocs.length > 0 ? [`- [ ] Wave 1 breakout files generated`, `- [ ] gen-status.json updated for every item`] : []),
538
- `- [ ] npx ai-spector index run after each wave`,
539
- `- [ ] npx ai-spector graph validate run at end`,
540
- `\`\`\``,
541
- ].join("\n");
542
- // Write Cursor skill
543
- const cursorSkillDir = join(root, ".cursor", "skills", `ai-spector-generate-${slug}`);
544
- await mkdir(cursorSkillDir, { recursive: true });
545
- await writeFile(join(cursorSkillDir, "SKILL.md"), cursorSkillContent + "\n", "utf8");
546
- // Write Claude skill
547
- const claudeSkillDir = join(root, ".claude", "skills", `ai-spector-generate-${slug}`);
548
- await mkdir(claudeSkillDir, { recursive: true });
549
- await writeFile(join(claudeSkillDir, "skill.md"), claudeSkillContent + "\n", "utf8");
550
- }
551
- async function writeDagFiles(root, dag, seeds) {
552
- const dagDir = join(root, ".ai-spector", ".docflow", "config");
553
- await mkdir(dagDir, { recursive: true });
554
- await writeJson(join(dagDir, "dag.srs.json"), dag);
555
- await writeJson(join(dagDir, "dag.srs.graph-seeds.json"), seeds);
556
- }
557
- async function restoreBuiltinDagFiles(root) {
558
- const { scaffoldBundleRoot } = await import("../config/load.js");
559
- const srcDir = join(scaffoldBundleRoot(), ".ai-spector", ".docflow", "config");
560
- const destDir = join(root, ".ai-spector", ".docflow", "config");
561
- await mkdir(destDir, { recursive: true });
562
- for (const name of ["dag.srs.json", "dag.srs.graph-seeds.json"]) {
563
- const src = join(srcDir, name);
564
- const dest = join(destDir, name);
565
- if (existsSync(src)) {
566
- await copyFile(src, dest);
567
- }
568
- }
569
- }
570
- // ---------------------------------------------------------------------------
571
- // template use <name>
572
- // ---------------------------------------------------------------------------
573
- async function runTemplateUse(name, opts) {
574
- const { root, config, configFile } = await loadConfigAndRoot(opts.cwd);
575
- if (name === "builtin" || name === "default") {
576
- if (config.packs) {
577
- delete config.packs;
578
- }
579
- await saveConfig(configFile, config);
580
- console.log("Switched to builtin templates. Restoring builtin DAG config...");
581
- await restoreBuiltinDagFiles(root);
582
- }
583
- else {
584
- const manifestPath = join(root, ".ai-spector", "packs", name, "manifest.json");
585
- if (!existsSync(manifestPath)) {
586
- console.error(`Pack "${name}" not found. Expected manifest at: ${manifestPath}`);
587
- process.exitCode = 1;
588
- return;
589
- }
590
- const manifest = await readJson(manifestPath);
591
- config.packs = { active: name };
592
- await saveConfig(configFile, config);
593
- console.log(`Switched to pack "${name}". Rebuilding registry, graph, and DAG config...`);
594
- // Write pack-derived DAG files, generate-hints.md, and dedicated generate skill
595
- const packDir = join(root, ".ai-spector", "packs", name);
596
- const { dag, seeds } = buildDagFromManifest(manifest);
597
- await writeDagFiles(root, dag, seeds);
598
- await writeGenerateHints(packDir, manifest);
599
- // Scan installed templates so context-map captures real placeholders
600
- const templatesDir = join(packDir, "templates");
601
- const scanForContextMap = (await pathExists(templatesDir))
602
- ? await scanTemplateFolder(templatesDir, templatesDir)
603
- : undefined;
604
- await writeContextMap(packDir, manifest, scanForContextMap);
605
- await writePackGenerateSkill(root, manifest);
606
- }
607
- const stats = await rebuildRegistryAndGraph(root, config);
608
- console.log(`Done. ${stats.documents} documents, ${stats.sections} sections, ` +
609
- `${stats.graphNodes} graph nodes, ${stats.graphEdges} edges.`);
610
- const activePack = config.packs?.active ?? "builtin";
611
- const docIdList = stats.documentIds?.map((id) => ` - ${id}`).join("\n") ??
612
- ` (run \`npx ai-spector template inspect ${activePack}\` to list them)`;
613
- console.log(`Active graph document ids (valid query seeds):\n${docIdList}`);
614
- if (activePack !== "builtin") {
615
- const activeManifestPath = join(root, ".ai-spector", "packs", activePack, "manifest.json");
616
- if (existsSync(activeManifestPath)) {
617
- const activeManifest = await readJson(activeManifestPath);
618
- const breakoutDocs = activeManifest.documents.filter((d) => d.perDomain);
619
- if (breakoutDocs.length > 0) {
620
- console.log(`\n⚠ Pack has ${breakoutDocs.length} breakout template(s) — generate primary docs first, then ask:\n` +
621
- breakoutDocs.map((d) => ` "generate breakout ${d.perDomain} files from the graph"`).join("\n") +
622
- `\n See: .ai-spector/packs/${activePack}/generate-hints.md`);
623
- }
624
- }
625
- console.log(`\nNote: .cursor/skills/ai-spector-generate-srs/references/runbook.md still references` +
626
- `\nbuiltin ids — update it or ask the agent to use the ids above when querying the graph.`);
627
- }
628
- }
629
- // ---------------------------------------------------------------------------
630
- // template inspect <name>
631
- // ---------------------------------------------------------------------------
632
- async function runTemplateInspect(name, opts) {
633
- const { root } = await loadConfigAndRoot(opts.cwd);
634
- let manifests;
635
- if (name === "builtin") {
636
- const { loadDocumentsManifest, loadBasicDesignListManifest } = await import("../config/load.js");
637
- const { manifest: srs } = await loadDocumentsManifest();
638
- const bd = await loadBasicDesignListManifest();
639
- manifests = [srs, bd];
640
- }
641
- else {
642
- const manifestPath = join(root, ".ai-spector", "packs", name, "manifest.json");
643
- if (!existsSync(manifestPath)) {
644
- console.error(`Pack "${name}" not found. Expected manifest at: ${manifestPath}`);
645
- process.exitCode = 1;
646
- return;
647
- }
648
- const manifest = await readJson(manifestPath);
649
- manifests = [manifest];
650
- }
651
- // Print table header
652
- const header = "documentId".padEnd(40) +
653
- "template".padEnd(40) +
654
- "output / outputPattern".padEnd(50) +
655
- "perDomain";
656
- const separator = "-".repeat(header.length);
657
- console.log(header);
658
- console.log(separator);
659
- for (const manifest of manifests) {
660
- for (const doc of manifest.documents) {
661
- const col1 = doc.documentId.padEnd(40);
662
- const col2 = doc.template.padEnd(40);
663
- const outputVal = doc.outputPattern ?? doc.output ?? "";
664
- const col3 = outputVal.padEnd(50);
665
- const col4 = doc.perDomain ?? "";
666
- console.log(`${col1}${col2}${col3}${col4}`);
667
- }
668
- }
669
- }
670
- // ---------------------------------------------------------------------------
671
- // template scan <path>
672
- // ---------------------------------------------------------------------------
673
- async function runTemplateScan(sourcePath, opts) {
674
- const resolvedSource = resolve(opts.cwd ?? process.cwd(), sourcePath);
675
- // Validate source is a directory
676
- if (!existsSync(resolvedSource)) {
677
- console.error(`Error: path does not exist: ${resolvedSource}`);
678
- process.exitCode = 1;
679
- return;
680
- }
681
- const { statSync } = await import("node:fs");
682
- if (!statSync(resolvedSource).isDirectory()) {
683
- console.error(`Error: path is not a directory: ${resolvedSource}`);
684
- process.exitCode = 1;
685
- return;
686
- }
687
- const { root } = await loadConfigAndRoot(opts.cwd);
688
- const stagingDir = join(root, ".ai-spector", "packs", ".staging");
689
- // Clear staging
690
- if (await pathExists(stagingDir)) {
691
- await rm(stagingDir, { recursive: true, force: true });
692
- }
693
- await mkdir(stagingDir, { recursive: true });
694
- // Scan
695
- const result = await scanTemplateFolder(resolvedSource, stagingDir);
696
- // Write scan-result.json
697
- const scanResultPath = join(stagingDir, "scan-result.json");
698
- await writeJson(scanResultPath, result);
699
- // Print summary
700
- console.log(`\nScanned ${resolvedSource}:`);
701
- console.log(` ${result.files.length} template file${result.files.length === 1 ? "" : "s"} found`);
702
- console.log();
703
- if (result.files.length > 0) {
704
- const fileCol = 32;
705
- const headCol = 10;
706
- const header = "File".padEnd(fileCol) + "Headings".padEnd(headCol) + "Placeholders";
707
- const divider = "─".repeat(header.length + 10);
708
- console.log(` ${header}`);
709
- console.log(` ${divider}`);
710
- for (const f of result.files) {
711
- const name = f.relativePath.padEnd(fileCol);
712
- const headings = String(f.headings.length).padEnd(headCol);
713
- const placeholders = f.placeholders.join(", ") || "(none)";
714
- console.log(` ${name}${headings}${placeholders}`);
715
- }
716
- console.log();
717
- }
718
- const relStaging = join(".ai-spector", "packs", ".staging", "scan-result.json");
719
- console.log(`Scan saved → ${relStaging}`);
720
- console.log();
721
- console.log(`Next step: open your AI IDE and ask:`);
722
- console.log(` "set up template pack"`);
723
- console.log(`The AI will read the scan result, ask you questions, refine`);
724
- console.log(`the templates, and write them to staging for you to review.`);
725
- }
726
- // ---------------------------------------------------------------------------
727
- // template install [--name <name>] [--dry-run]
728
- // ---------------------------------------------------------------------------
729
- async function runTemplateInstall(opts) {
730
- const { root, config, configFile } = await loadConfigAndRoot(opts.cwd);
731
- const stagingDir = join(root, ".ai-spector", "packs", ".staging");
732
- // Check scan-result.json exists
733
- const scanResultPath = join(stagingDir, "scan-result.json");
734
- if (!(await pathExists(scanResultPath))) {
735
- console.error('Error: scan-result.json not found in staging. Run `template scan` first.');
736
- process.exitCode = 1;
737
- return;
738
- }
739
- // Check staleness (> 24h)
740
- const scanResult = await readJson(scanResultPath);
741
- const scannedAt = new Date(scanResult.scannedAt);
742
- const ageMs = Date.now() - scannedAt.getTime();
743
- const ageHours = Math.floor(ageMs / (1000 * 60 * 60));
744
- if (ageMs > 24 * 60 * 60 * 1000) {
745
- console.warn(`Warning: scan is ${ageHours} hours old — the AI may have worked with stale context.`);
746
- }
747
- // Check manifest.json exists
748
- const stagingManifestPath = join(stagingDir, "manifest.json");
749
- if (!(await pathExists(stagingManifestPath))) {
750
- console.error('Error: manifest.json not found in staging. Ask the AI to complete the setup workflow.');
751
- process.exitCode = 1;
752
- return;
753
- }
754
- // Load + validate manifest
755
- const rawManifest = await readJson(stagingManifestPath);
756
- const { valid, errors } = validatePackManifest(rawManifest);
757
- if (!valid) {
758
- console.error("manifest.json validation failed:");
759
- for (const err of errors) {
760
- console.error(` - ${err}`);
761
- }
762
- process.exitCode = 1;
763
- return;
764
- }
765
- const manifest = rawManifest;
766
- // Determine pack name
767
- const packName = opts.name ?? manifest.packName;
768
- // Check all template files exist in staging/templates/
769
- const stagingTemplatesDir = join(stagingDir, manifest.templatesDir ?? "templates");
770
- const missing = [];
771
- for (const doc of manifest.documents) {
772
- const tplPath = join(stagingTemplatesDir, doc.template);
773
- if (!(await pathExists(tplPath))) {
774
- missing.push(doc.template);
775
- }
776
- }
777
- if (missing.length > 0) {
778
- console.error("Error: the following template files are missing from staging:");
779
- for (const f of missing) {
780
- console.error(` - ${f}`);
781
- }
782
- process.exitCode = 1;
783
- return;
784
- }
785
- // Dry run — stop here
786
- if (opts.dryRun) {
787
- console.log(`Dry run complete — all checks passed. Pack: ${packName}`);
788
- return;
789
- }
790
- // Destination
791
- const destDir = join(root, ".ai-spector", "packs", packName);
792
- // Remove existing if present
793
- if (await pathExists(destDir)) {
794
- await rm(destDir, { recursive: true, force: true });
795
- }
796
- // Copy templates
797
- const destTemplatesDir = join(destDir, "templates");
798
- await copyTree(stagingTemplatesDir, destTemplatesDir);
799
- // Write manifest to destination (with resolved packName)
800
- const finalManifest = { ...manifest, packName };
801
- await writeJson(join(destDir, "manifest.json"), finalManifest);
802
- // Patch config FIRST
803
- const previousPacks = config.packs;
804
- config.packs = { active: packName };
805
- await saveConfig(configFile, config);
806
- // Build registry + graph, roll back on failure
807
- let stats;
808
- try {
809
- stats = await rebuildRegistryAndGraph(root, config);
810
- }
811
- catch (err) {
812
- // Roll back config
813
- if (previousPacks === undefined) {
814
- delete config.packs;
815
- }
816
- else {
817
- config.packs = previousPacks;
818
- }
819
- await saveConfig(configFile, config);
820
- throw err;
821
- }
822
- // Write pack-derived DAG files, generate-hints.md, and dedicated generate skill
823
- const { dag, seeds } = buildDagFromManifest(finalManifest);
824
- await writeDagFiles(root, dag, seeds);
825
- await writeGenerateHints(destDir, finalManifest);
826
- await writeContextMap(destDir, finalManifest, scanResult);
827
- const stagedSkillPath = join(stagingDir, "generate-skill.md");
828
- await writePackGenerateSkill(root, finalManifest, stagedSkillPath);
829
- // skill-hints.md — if the AI wrote one in staging, copy to pack dir
830
- const skillHintsPath = join(stagingDir, "skill-hints.md");
831
- if (await pathExists(skillHintsPath)) {
832
- await copyFile(skillHintsPath, join(destDir, "skill-hints.md"));
833
- }
834
- // Clear staging
835
- await rm(stagingDir, { recursive: true, force: true });
836
- // Print summary
837
- console.log(`\n✓ Pack '${packName}' installed and activated.\n`);
838
- console.log(` Documents : ${stats.documents}`);
839
- console.log(` Sections : ${stats.sections}`);
840
- console.log(` Graph : ${stats.graphNodes} nodes, ${stats.graphEdges} edges`);
841
- console.log();
842
- const usedAiSkill = existsSync(stagedSkillPath);
843
- console.log(` Templates → .ai-spector/packs/${packName}/templates/`);
844
- console.log(` Active → docflow.config.json updated`);
845
- console.log(` DAG → .ai-spector/.docflow/config/dag.srs.json updated`);
846
- console.log(` Skill → .cursor/skills/ai-spector-generate-${packName}/SKILL.md ${usedAiSkill ? "(AI-written)" : "(auto-generated from manifest)"}`);
847
- console.log(` → .claude/skills/ai-spector-generate-${packName}/skill.md`);
848
- const breakoutDocs = finalManifest.documents.filter((d) => d.perDomain);
849
- if (breakoutDocs.length > 0) {
850
- console.log();
851
- console.log(` ⚠ This pack includes ${breakoutDocs.length} per-domain breakout template(s):`);
852
- for (const d of breakoutDocs) {
853
- console.log(` ${d.documentId} (perDomain: ${d.perDomain})`);
854
- console.log(` output: ${d.outputPattern ?? d.output ?? "(see manifest)"}`);
855
- }
856
- console.log();
857
- console.log(` Breakout files are NOT generated automatically.`);
858
- console.log(` After "generate SRS", ask your AI IDE:`);
859
- console.log(` "generate breakout ${breakoutDocs[0]?.perDomain ?? "requirement"} files from the graph"`);
860
- console.log(` Reference: .ai-spector/packs/${packName}/generate-hints.md`);
861
- }
862
- console.log();
863
- console.log(`Next: ask your AI to "generate <document>" to use the new template.`);
864
- }
865
- // ---------------------------------------------------------------------------
866
- // template verify <name>
867
- // ---------------------------------------------------------------------------
868
- /**
869
- * Verify a pack is correctly wired:
870
- * - All template files referenced in manifest exist on disk
871
- * - context-map.json has no TODO entries (warns, not error)
872
- * - generate-hints.md and dag files exist
873
- * - All output paths / outputPatterns are non-empty
874
- */
875
- async function runTemplateVerify(name, opts) {
876
- const { root, config } = await loadConfigAndRoot(opts.cwd);
877
- const resolvedName = name === "active" ? (config.packs?.active ?? "builtin") : name;
878
- if (resolvedName === "builtin") {
879
- console.log("Builtin pack — no verification needed.");
880
- return;
881
- }
882
- const packDir = join(root, ".ai-spector", "packs", resolvedName);
883
- const manifestPath = join(packDir, "manifest.json");
884
- if (!(await pathExists(manifestPath))) {
885
- console.error(`Error: pack "${resolvedName}" not found at ${packDir}`);
886
- process.exitCode = 1;
887
- return;
888
- }
889
- const manifest = await readJson(manifestPath);
890
- const errors = [];
891
- const warnings = [];
892
- // 1. Template files
893
- for (const doc of manifest.documents) {
894
- const tplPath = join(packDir, "templates", doc.template);
895
- if (!(await pathExists(tplPath))) {
896
- errors.push(`Missing template file: templates/${doc.template} (documentId: ${doc.documentId})`);
897
- }
898
- }
899
- // 2. Output paths defined
900
- for (const doc of manifest.documents) {
901
- const hasOutput = typeof doc.output === "string" && doc.output.length > 0;
902
- const hasPattern = typeof doc.outputPattern === "string" && doc.outputPattern.length > 0;
903
- if (!hasOutput && !hasPattern) {
904
- errors.push(`Document "${doc.documentId}" has no output or outputPattern`);
905
- }
906
- }
907
- // 3. generate-hints.md and DAG files
908
- for (const f of ["generate-hints.md", "context-map.json"]) {
909
- if (!(await pathExists(join(packDir, f)))) {
910
- warnings.push(`${f} is missing — run \`template use ${resolvedName}\` to regenerate`);
911
- }
912
- }
913
- const dagDir = join(root, ".ai-spector", ".docflow", "config");
914
- if (config.packs?.active === resolvedName) {
915
- for (const f of ["dag.srs.json", "dag.srs.graph-seeds.json"]) {
916
- if (!(await pathExists(join(dagDir, f)))) {
917
- warnings.push(`${f} is missing — run \`template use ${resolvedName}\` to regenerate`);
918
- }
919
- }
920
- }
921
- // 4. context-map TODO entries
922
- const contextMapPath = join(packDir, "context-map.json");
923
- if (await pathExists(contextMapPath)) {
924
- try {
925
- const cm = await readJson(contextMapPath);
926
- const todos = Object.entries(cm.placeholders ?? {})
927
- .filter(([, v]) => v.source === "TODO")
928
- .map(([k]) => k);
929
- if (todos.length > 0) {
930
- warnings.push(`context-map.json has ${todos.length} unresolved placeholder(s): ${todos.join(", ")}` +
931
- `\n Edit .ai-spector/packs/${resolvedName}/context-map.json or ask the AI to fill them in.`);
932
- }
933
- }
934
- catch {
935
- warnings.push("context-map.json could not be parsed");
936
- }
937
- }
938
- // 5. gen-status.json — show missing breakout items if present
939
- const genStatusPath = join(packDir, "gen-status.json");
940
- if (await pathExists(genStatusPath)) {
941
- try {
942
- const gs = await readJson(genStatusPath);
943
- const blocked = (gs.items ?? []).filter((i) => i.status === "blocked");
944
- const pending = (gs.items ?? []).filter((i) => i.status === "pending");
945
- if (blocked.length > 0) {
946
- warnings.push(`${blocked.length} breakout item(s) are blocked:\n` +
947
- blocked.map((i) => ` ${i.itemId}: ${i.blockedReason ?? "no reason given"}`).join("\n"));
948
- }
949
- if (pending.length > 0) {
950
- warnings.push(`${pending.length} breakout item(s) still pending: ${pending.map((i) => i.itemId).join(", ")}`);
951
- }
952
- }
953
- catch {
954
- warnings.push("gen-status.json could not be parsed");
955
- }
956
- }
957
- // Report
958
- if (errors.length === 0 && warnings.length === 0) {
959
- console.log(`✓ Pack "${resolvedName}" verified — no issues found.`);
960
- return;
961
- }
962
- if (warnings.length > 0) {
963
- console.log(`Warnings for pack "${resolvedName}":`);
964
- for (const w of warnings)
965
- console.warn(` ⚠ ${w}`);
966
- }
967
- if (errors.length > 0) {
968
- console.log(`\nErrors for pack "${resolvedName}":`);
969
- for (const e of errors)
970
- console.error(` ✗ ${e}`);
971
- process.exitCode = 1;
972
- }
973
- }
974
- // ---------------------------------------------------------------------------
975
- // template status [name]
976
- // ---------------------------------------------------------------------------
977
- /**
978
- * Show generation progress for a pack's breakout items.
979
- * Reads gen-status.json if present; otherwise reports no tracking data.
980
- */
981
- async function runTemplateStatus(name, opts) {
982
- const { root, config } = await loadConfigAndRoot(opts.cwd);
983
- const resolvedName = name ?? config.packs?.active ?? "builtin";
984
- if (resolvedName === "builtin") {
985
- console.log("Builtin pack has no breakout items to track.");
986
- return;
987
- }
988
- const packDir = join(root, ".ai-spector", "packs", resolvedName);
989
- const manifest = await readJson(join(packDir, "manifest.json")).catch(() => null);
990
- if (!manifest) {
991
- console.error(`Error: pack "${resolvedName}" not found.`);
992
- process.exitCode = 1;
993
- return;
994
- }
995
- const breakoutDocs = manifest.documents.filter((d) => d.perDomain);
996
- if (breakoutDocs.length === 0) {
997
- console.log(`Pack "${resolvedName}" has no breakout templates — nothing to track.`);
998
- return;
999
- }
1000
- const genStatusPath = join(packDir, "gen-status.json");
1001
- if (!(await pathExists(genStatusPath))) {
1002
- console.log(`No gen-status.json found for pack "${resolvedName}".`);
1003
- console.log(`This file is written by the AI as it generates breakout items.`);
1004
- console.log(`Run \`template verify ${resolvedName}\` after generation to check for issues.`);
1005
- return;
1006
- }
1007
- const gs = await readJson(genStatusPath);
1008
- const items = gs.items ?? [];
1009
- const done = items.filter((i) => i.status === "done" && !i.staleSince);
1010
- const stale = items.filter((i) => i.status === "done" && i.staleSince);
1011
- const pending = items.filter((i) => i.status === "pending");
1012
- const blocked = items.filter((i) => i.status === "blocked");
1013
- console.log(`\nGeneration status for pack "${resolvedName}"\n`);
1014
- console.log(` Total : ${items.length}`);
1015
- console.log(` Done : ${done.length}`);
1016
- console.log(` Stale : ${stale.length}${stale.length > 0 ? " ← run \`template regen\` to see details" : ""}`);
1017
- console.log(` Pending : ${pending.length}`);
1018
- console.log(` Blocked : ${blocked.length}`);
1019
- if (stale.length > 0) {
1020
- console.log(`\n⚠ Stale (source changed since generation):`);
1021
- for (const i of stale) {
1022
- console.log(` ${i.itemId} → ${i.outputFile ?? "(no output path)"} (stale since ${i.staleSince.slice(0, 10)})`);
1023
- }
1024
- }
1025
- if (done.length > 0) {
1026
- console.log(`\n✓ Done:`);
1027
- for (const i of done) {
1028
- console.log(` ${i.itemId} → ${i.outputFile ?? "(no output path)"}${i.generatedAt ? ` (${i.generatedAt.slice(0, 10)})` : ""}`);
1029
- }
1030
- }
1031
- if (pending.length > 0) {
1032
- console.log(`\n○ Pending:`);
1033
- for (const i of pending)
1034
- console.log(` ${i.itemId}`);
1035
- }
1036
- if (blocked.length > 0) {
1037
- console.log(`\n⚠ Blocked (needs human input):`);
1038
- for (const i of blocked)
1039
- console.log(` ${i.itemId}: ${i.blockedReason ?? "no reason given"}`);
1040
- }
1041
- if (blocked.length > 0 || pending.length > 0) {
1042
- console.log(`\nTo resume: ask your AI to continue generating breakout items for pack "${resolvedName}".`);
1043
- }
1044
- }
1045
- // ---------------------------------------------------------------------------
1046
- // template remove <name>
1047
- // ---------------------------------------------------------------------------
1048
- async function runTemplateRemove(name, opts) {
1049
- const { root, config } = await loadConfigAndRoot(opts.cwd);
1050
- const packDir = join(root, ".ai-spector", "packs", name);
1051
- if (!(await pathExists(packDir))) {
1052
- console.error(`Error: pack "${name}" is not installed.`);
1053
- process.exitCode = 1;
1054
- return;
1055
- }
1056
- if (config.packs?.active === name) {
1057
- console.error(`Error: pack '${name}' is currently active. Run \`template use builtin\` first.`);
1058
- process.exitCode = 1;
1059
- return;
1060
- }
1061
- await rm(packDir, { recursive: true, force: true });
1062
- console.log(`Removed pack '${name}'.`);
1063
- }
1064
- // ---------------------------------------------------------------------------
1065
- // template export <output-path>
1066
- // ---------------------------------------------------------------------------
1067
- async function runTemplateExport(outputPath, opts) {
1068
- const cwd = opts.cwd ?? process.cwd();
1069
- const { root, config } = await loadConfigAndRoot(cwd);
1070
- // Determine pack name to export
1071
- let packName = opts.pack ?? config.packs?.active ?? "builtin";
1072
- if (!packName || packName === "default")
1073
- packName = "builtin";
1074
- // Resolve output path
1075
- const outputAbs = resolve(cwd, outputPath);
1076
- // Check if output exists
1077
- if (await pathExists(outputAbs)) {
1078
- if (!opts.overwrite) {
1079
- console.error("Output path already exists. Use --overwrite to replace it.");
1080
- process.exitCode = 1;
1081
- return;
1082
- }
1083
- await rm(outputAbs, { recursive: true, force: true });
1084
- }
1085
- // Create output dirs
1086
- const outputTemplatesDir = join(outputAbs, "templates");
1087
- await mkdir(outputTemplatesDir, { recursive: true });
1088
- let manifest;
1089
- let templateCount = 0;
1090
- if (packName === "builtin") {
1091
- // Load both builtin manifests
1092
- const { bundleRoot, manifest: srsManifest } = await loadDocumentsManifest();
1093
- const bdManifest = await loadBasicDesignListManifest();
1094
- // Merge documents, copying templates while preserving subdirectory structure
1095
- const allDocs = [];
1096
- for (const srcManifest of [srsManifest, bdManifest]) {
1097
- const srcTemplatesDir = join(bundleRoot, srcManifest.templatesDir);
1098
- for (const doc of srcManifest.documents) {
1099
- // srcManifest.templatesDir is e.g. "templates/srs" — extract the subdir
1100
- // relative to the root "templates/" folder
1101
- const subdir = srcManifest.templatesDir.replace(/^templates\/?/, "");
1102
- const relPath = subdir ? join(subdir, doc.template) : doc.template;
1103
- const srcFile = join(srcTemplatesDir, doc.template);
1104
- const destFile = join(outputTemplatesDir, relPath);
1105
- // Ensure subdirectory exists
1106
- await mkdir(join(outputTemplatesDir, subdir || "."), { recursive: true });
1107
- if (await pathExists(srcFile)) {
1108
- await copyFile(srcFile, destFile);
1109
- templateCount++;
1110
- }
1111
- allDocs.push({ ...doc, template: relPath });
1112
- }
1113
- }
1114
- manifest = {
1115
- version: srsManifest.version,
1116
- name: "builtin",
1117
- packName: "builtin",
1118
- templatesDir: "templates",
1119
- nodePrefix: "doc.srs",
1120
- perDomainTemplates: {
1121
- useCase: "doc.srs.use-case-detail",
1122
- feature: "doc.srs.system-feature-detail",
1123
- },
1124
- defaultListedIn: {
1125
- useCase: "doc.srs.use-cases",
1126
- feature: "doc.srs.system-features-list",
1127
- actor: "doc.srs.use-cases",
1128
- },
1129
- documents: allDocs,
1130
- };
1131
- }
1132
- else {
1133
- // Custom pack
1134
- const packDir = join(root, ".ai-spector", "packs", packName);
1135
- const manifestPath = join(packDir, "manifest.json");
1136
- if (!(await pathExists(manifestPath))) {
1137
- console.error(`Pack "${packName}" not found. Expected manifest at: ${manifestPath}`);
1138
- process.exitCode = 1;
1139
- return;
1140
- }
1141
- manifest = await readJson(manifestPath);
1142
- const srcTemplatesDir = join(packDir, manifest.templatesDir ?? "templates");
1143
- // Copy templates preserving structure
1144
- if (await pathExists(srcTemplatesDir)) {
1145
- await copyTree(srcTemplatesDir, outputTemplatesDir);
1146
- // Count template files
1147
- const countFiles = async (dir) => {
1148
- let count = 0;
1149
- try {
1150
- const entries = await readdir(dir, { withFileTypes: true });
1151
- for (const entry of entries) {
1152
- if (entry.isDirectory()) {
1153
- count += await countFiles(join(dir, entry.name));
1154
- }
1155
- else if (entry.name.endsWith(".md")) {
1156
- count++;
1157
- }
1158
- }
1159
- }
1160
- catch { /* ignore */ }
1161
- return count;
1162
- };
1163
- templateCount = await countFiles(srcTemplatesDir);
1164
- }
1165
- // Override templatesDir to "templates" in output
1166
- manifest = { ...manifest, templatesDir: "templates" };
1167
- // Copy skill-hints.md if present
1168
- const skillHintsSrc = join(packDir, "skill-hints.md");
1169
- if (await pathExists(skillHintsSrc)) {
1170
- await copyFile(skillHintsSrc, join(outputAbs, "skill-hints.md"));
1171
- }
1172
- }
1173
- // Write manifest.json
1174
- await writeJson(join(outputAbs, "manifest.json"), manifest);
1175
- // Print summary
1176
- const relOutput = outputPath.startsWith("/") ? outputPath : `./${outputPath}`;
1177
- console.log(`\n✓ Exported pack '${packName}' to ${relOutput}/\n`);
1178
- console.log(` Templates : ${templateCount} files`);
1179
- console.log(` Manifest : ${join(outputPath, "manifest.json")}`);
1180
- console.log();
1181
- console.log("To use this template in another project:");
1182
- console.log(" 1. Copy the folder to the other project's workspace");
1183
- console.log(` 2. Run: npx ai-spector template scan ./${outputPath}`);
1184
- console.log(' 3. Ask your AI: "set up template pack"');
1185
- }
1186
- // ---------------------------------------------------------------------------
1187
- // Command group registration
1188
- // ---------------------------------------------------------------------------
1189
- export function registerTemplateCommand(program) {
1190
- const template = program
1191
- .command("template")
1192
- .description("Template pack management: list, use, inspect, scan, install, remove");
1193
- template
1194
- .command("list")
1195
- .description("List installed template packs and show which is active")
1196
- .option("-C, --cwd <path>", "Project root", process.cwd())
1197
- .action(async (opts) => {
1198
- await runTemplateList({ cwd: resolve(opts.cwd ?? process.cwd()) });
1199
- });
1200
- template
1201
- .command("use <name>")
1202
- .description('Switch to a template pack (use "builtin" to revert to default). Re-indexes graph automatically.')
1203
- .option("-C, --cwd <path>", "Project root", process.cwd())
1204
- .action(async (name, opts) => {
1205
- await runTemplateUse(name, { cwd: resolve(opts.cwd ?? process.cwd()) });
1206
- });
1207
- template
1208
- .command("inspect <name>")
1209
- .description('Inspect a pack manifest as a table (use "builtin" to inspect the builtin templates).')
1210
- .option("-C, --cwd <path>", "Project root", process.cwd())
1211
- .action(async (name, opts) => {
1212
- await runTemplateInspect(name, { cwd: resolve(opts.cwd ?? process.cwd()) });
1213
- });
1214
- template
1215
- .command("scan <path>")
1216
- .description("Walk a folder of .md template files, extract headings + placeholders, write scan-result.json to staging.")
1217
- .option("-C, --cwd <path>", "Project root", process.cwd())
1218
- .action(async (sourcePath, opts) => {
1219
- await runTemplateScan(sourcePath, { cwd: resolve(opts.cwd ?? process.cwd()) });
1220
- });
1221
- template
1222
- .command("install")
1223
- .description("Install a template pack from staging (manifest.json + templates/ written by AI).")
1224
- .option("-C, --cwd <path>", "Project root", process.cwd())
1225
- .option("--name <name>", "Override pack name from manifest")
1226
- .option("--dry-run", "Validate and print without writing anything")
1227
- .action(async (opts) => {
1228
- await runTemplateInstall({
1229
- cwd: resolve(opts.cwd ?? process.cwd()),
1230
- name: opts.name,
1231
- dryRun: Boolean(opts.dryRun),
1232
- });
1233
- });
1234
- template
1235
- .command("verify [name]")
1236
- .description('Verify a pack is correctly wired: templates exist, output paths defined, context-map TODOs flagged. Use "active" or omit to check the active pack.')
1237
- .option("-C, --cwd <path>", "Project root", process.cwd())
1238
- .action(async (name, opts) => {
1239
- await runTemplateVerify(name ?? "active", { cwd: resolve(opts.cwd ?? process.cwd()) });
1240
- });
1241
- template
1242
- .command("status [name]")
1243
- .description("Show breakout-item generation progress for a pack (reads gen-status.json written by the AI during generation).")
1244
- .option("-C, --cwd <path>", "Project root", process.cwd())
1245
- .action(async (name, opts) => {
1246
- await runTemplateStatus(name, { cwd: resolve(opts.cwd ?? process.cwd()) });
1247
- });
1248
- template
1249
- .command("regen [pack]")
1250
- .description("Detect which pack output files are stale after source changes, write regen-plan.md, and update gen-status.json. Uses git diff by default.")
1251
- .option("-C, --cwd <path>", "Project root", process.cwd())
1252
- .option("--origin <nodeId>", "Use a specific graph node as impact origin instead of git diff")
1253
- .option("--json", "Output regen plan as JSON")
1254
- .option("--dry-run", "Print stale files without writing regen-plan.md")
1255
- .action(async (pack, opts) => {
1256
- await runTemplateRegen({
1257
- cwd: resolve(opts.cwd ?? process.cwd()),
1258
- pack,
1259
- origin: opts.origin,
1260
- json: Boolean(opts.json),
1261
- dryRun: Boolean(opts.dryRun),
1262
- });
1263
- });
1264
- template
1265
- .command("remove <name>")
1266
- .description("Remove an installed template pack by name.")
1267
- .option("-C, --cwd <path>", "Project root", process.cwd())
1268
- .action(async (name, opts) => {
1269
- await runTemplateRemove(name, { cwd: resolve(opts.cwd ?? process.cwd()) });
1270
- });
1271
- template
1272
- .command("export <output-path>")
1273
- .description("Export the active (or specified) template pack as a portable folder for use in another project.")
1274
- .option("-C, --cwd <path>", "Project root", process.cwd())
1275
- .option("--pack <name>", "Pack to export (default: active pack)")
1276
- .option("--overwrite", "Replace output path if it already exists")
1277
- .action(async (outputPath, opts) => {
1278
- await runTemplateExport(outputPath, {
1279
- cwd: resolve(opts.cwd ?? process.cwd()),
1280
- pack: opts.pack,
1281
- overwrite: Boolean(opts.overwrite),
1282
- });
1283
- });
1284
- }
1285
- //# sourceMappingURL=template.js.map