@seanmars/tospec 0.4.2

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 (402) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/assets/dashboard/app.js +1032 -0
  4. package/assets/dashboard/chart.umd.js +14 -0
  5. package/assets/dashboard/index.html +30 -0
  6. package/assets/dashboard/style.css +675 -0
  7. package/bin/tospec.js +5 -0
  8. package/dist/cli/index.d.ts +5 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +330 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/commands/config.d.ts +36 -0
  13. package/dist/commands/config.d.ts.map +1 -0
  14. package/dist/commands/config.js +486 -0
  15. package/dist/commands/config.js.map +1 -0
  16. package/dist/commands/dashboard.d.ts +40 -0
  17. package/dist/commands/dashboard.d.ts.map +1 -0
  18. package/dist/commands/dashboard.js +385 -0
  19. package/dist/commands/dashboard.js.map +1 -0
  20. package/dist/commands/shared-output.d.ts +24 -0
  21. package/dist/commands/shared-output.d.ts.map +1 -0
  22. package/dist/commands/shared-output.js +51 -0
  23. package/dist/commands/shared-output.js.map +1 -0
  24. package/dist/commands/show.d.ts +17 -0
  25. package/dist/commands/show.d.ts.map +1 -0
  26. package/dist/commands/show.js +164 -0
  27. package/dist/commands/show.js.map +1 -0
  28. package/dist/commands/validate.d.ts +51 -0
  29. package/dist/commands/validate.d.ts.map +1 -0
  30. package/dist/commands/validate.js +416 -0
  31. package/dist/commands/validate.js.map +1 -0
  32. package/dist/commands/workflow/index.d.ts +17 -0
  33. package/dist/commands/workflow/index.d.ts.map +1 -0
  34. package/dist/commands/workflow/index.js +12 -0
  35. package/dist/commands/workflow/index.js.map +1 -0
  36. package/dist/commands/workflow/instructions.d.ts +35 -0
  37. package/dist/commands/workflow/instructions.d.ts.map +1 -0
  38. package/dist/commands/workflow/instructions.js +359 -0
  39. package/dist/commands/workflow/instructions.js.map +1 -0
  40. package/dist/commands/workflow/new-change.d.ts +17 -0
  41. package/dist/commands/workflow/new-change.d.ts.map +1 -0
  42. package/dist/commands/workflow/new-change.js +97 -0
  43. package/dist/commands/workflow/new-change.js.map +1 -0
  44. package/dist/commands/workflow/schemas.d.ts +10 -0
  45. package/dist/commands/workflow/schemas.d.ts.map +1 -0
  46. package/dist/commands/workflow/schemas.js +33 -0
  47. package/dist/commands/workflow/schemas.js.map +1 -0
  48. package/dist/commands/workflow/shared.d.ts +63 -0
  49. package/dist/commands/workflow/shared.d.ts.map +1 -0
  50. package/dist/commands/workflow/shared.js +111 -0
  51. package/dist/commands/workflow/shared.js.map +1 -0
  52. package/dist/commands/workflow/status.d.ts +14 -0
  53. package/dist/commands/workflow/status.d.ts.map +1 -0
  54. package/dist/commands/workflow/status.js +77 -0
  55. package/dist/commands/workflow/status.js.map +1 -0
  56. package/dist/commands/workflow/templates.d.ts +16 -0
  57. package/dist/commands/workflow/templates.d.ts.map +1 -0
  58. package/dist/commands/workflow/templates.js +60 -0
  59. package/dist/commands/workflow/templates.js.map +1 -0
  60. package/dist/core/archive.d.ts +33 -0
  61. package/dist/core/archive.d.ts.map +1 -0
  62. package/dist/core/archive.js +585 -0
  63. package/dist/core/archive.js.map +1 -0
  64. package/dist/core/artifact-graph/graph.d.ts +56 -0
  65. package/dist/core/artifact-graph/graph.d.ts.map +1 -0
  66. package/dist/core/artifact-graph/graph.js +141 -0
  67. package/dist/core/artifact-graph/graph.js.map +1 -0
  68. package/dist/core/artifact-graph/index.d.ts +9 -0
  69. package/dist/core/artifact-graph/index.d.ts.map +1 -0
  70. package/dist/core/artifact-graph/index.js +14 -0
  71. package/dist/core/artifact-graph/index.js.map +1 -0
  72. package/dist/core/artifact-graph/instruction-loader.d.ts +188 -0
  73. package/dist/core/artifact-graph/instruction-loader.d.ts.map +1 -0
  74. package/dist/core/artifact-graph/instruction-loader.js +243 -0
  75. package/dist/core/artifact-graph/instruction-loader.js.map +1 -0
  76. package/dist/core/artifact-graph/outputs.d.ts +14 -0
  77. package/dist/core/artifact-graph/outputs.d.ts.map +1 -0
  78. package/dist/core/artifact-graph/outputs.js +39 -0
  79. package/dist/core/artifact-graph/outputs.js.map +1 -0
  80. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  81. package/dist/core/artifact-graph/resolver.d.ts.map +1 -0
  82. package/dist/core/artifact-graph/resolver.js +257 -0
  83. package/dist/core/artifact-graph/resolver.js.map +1 -0
  84. package/dist/core/artifact-graph/schema.d.ts +13 -0
  85. package/dist/core/artifact-graph/schema.d.ts.map +1 -0
  86. package/dist/core/artifact-graph/schema.js +108 -0
  87. package/dist/core/artifact-graph/schema.js.map +1 -0
  88. package/dist/core/artifact-graph/state.d.ts +12 -0
  89. package/dist/core/artifact-graph/state.d.ts.map +1 -0
  90. package/dist/core/artifact-graph/state.js +31 -0
  91. package/dist/core/artifact-graph/state.js.map +1 -0
  92. package/dist/core/artifact-graph/types.d.ts +55 -0
  93. package/dist/core/artifact-graph/types.d.ts.map +1 -0
  94. package/dist/core/artifact-graph/types.js +38 -0
  95. package/dist/core/artifact-graph/types.js.map +1 -0
  96. package/dist/core/available-tools.d.ts +17 -0
  97. package/dist/core/available-tools.d.ts.map +1 -0
  98. package/dist/core/available-tools.js +43 -0
  99. package/dist/core/available-tools.js.map +1 -0
  100. package/dist/core/change-metadata/index.d.ts +2 -0
  101. package/dist/core/change-metadata/index.d.ts.map +1 -0
  102. package/dist/core/change-metadata/index.js +2 -0
  103. package/dist/core/change-metadata/index.js.map +1 -0
  104. package/dist/core/change-metadata/schema.d.ts +12 -0
  105. package/dist/core/change-metadata/schema.d.ts.map +1 -0
  106. package/dist/core/change-metadata/schema.js +15 -0
  107. package/dist/core/change-metadata/schema.js.map +1 -0
  108. package/dist/core/change-presenter.d.ts +24 -0
  109. package/dist/core/change-presenter.d.ts.map +1 -0
  110. package/dist/core/change-presenter.js +135 -0
  111. package/dist/core/change-presenter.js.map +1 -0
  112. package/dist/core/change-status-policy.d.ts +35 -0
  113. package/dist/core/change-status-policy.d.ts.map +1 -0
  114. package/dist/core/change-status-policy.js +34 -0
  115. package/dist/core/change-status-policy.js.map +1 -0
  116. package/dist/core/command-generation/adapters/claude.d.ts +14 -0
  117. package/dist/core/command-generation/adapters/claude.d.ts.map +1 -0
  118. package/dist/core/command-generation/adapters/claude.js +38 -0
  119. package/dist/core/command-generation/adapters/claude.js.map +1 -0
  120. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  121. package/dist/core/command-generation/adapters/cursor.d.ts.map +1 -0
  122. package/dist/core/command-generation/adapters/cursor.js +31 -0
  123. package/dist/core/command-generation/adapters/cursor.js.map +1 -0
  124. package/dist/core/command-generation/adapters/index.d.ts +8 -0
  125. package/dist/core/command-generation/adapters/index.d.ts.map +1 -0
  126. package/dist/core/command-generation/adapters/index.js +8 -0
  127. package/dist/core/command-generation/adapters/index.js.map +1 -0
  128. package/dist/core/command-generation/generator.d.ts +21 -0
  129. package/dist/core/command-generation/generator.d.ts.map +1 -0
  130. package/dist/core/command-generation/generator.js +27 -0
  131. package/dist/core/command-generation/generator.js.map +1 -0
  132. package/dist/core/command-generation/index.d.ts +22 -0
  133. package/dist/core/command-generation/index.d.ts.map +1 -0
  134. package/dist/core/command-generation/index.js +24 -0
  135. package/dist/core/command-generation/index.js.map +1 -0
  136. package/dist/core/command-generation/registry.d.ts +24 -0
  137. package/dist/core/command-generation/registry.d.ts.map +1 -0
  138. package/dist/core/command-generation/registry.js +38 -0
  139. package/dist/core/command-generation/registry.js.map +1 -0
  140. package/dist/core/command-generation/types.d.ts +56 -0
  141. package/dist/core/command-generation/types.d.ts.map +1 -0
  142. package/dist/core/command-generation/types.js +8 -0
  143. package/dist/core/command-generation/types.js.map +1 -0
  144. package/dist/core/command-generation/yaml.d.ts +22 -0
  145. package/dist/core/command-generation/yaml.d.ts.map +1 -0
  146. package/dist/core/command-generation/yaml.js +38 -0
  147. package/dist/core/command-generation/yaml.js.map +1 -0
  148. package/dist/core/config-prompts.d.ts +9 -0
  149. package/dist/core/config-prompts.d.ts.map +1 -0
  150. package/dist/core/config-prompts.js +34 -0
  151. package/dist/core/config-prompts.js.map +1 -0
  152. package/dist/core/config-schema.d.ts +87 -0
  153. package/dist/core/config-schema.d.ts.map +1 -0
  154. package/dist/core/config-schema.js +239 -0
  155. package/dist/core/config-schema.js.map +1 -0
  156. package/dist/core/config.d.ts +19 -0
  157. package/dist/core/config.d.ts.map +1 -0
  158. package/dist/core/config.js +14 -0
  159. package/dist/core/config.js.map +1 -0
  160. package/dist/core/converters/json-converter.d.ts +6 -0
  161. package/dist/core/converters/json-converter.d.ts.map +1 -0
  162. package/dist/core/converters/json-converter.js +51 -0
  163. package/dist/core/converters/json-converter.js.map +1 -0
  164. package/dist/core/dashboard-activity.d.ts +50 -0
  165. package/dist/core/dashboard-activity.d.ts.map +1 -0
  166. package/dist/core/dashboard-activity.js +147 -0
  167. package/dist/core/dashboard-activity.js.map +1 -0
  168. package/dist/core/dashboard-data.d.ts +100 -0
  169. package/dist/core/dashboard-data.d.ts.map +1 -0
  170. package/dist/core/dashboard-data.js +368 -0
  171. package/dist/core/dashboard-data.js.map +1 -0
  172. package/dist/core/global-config.d.ts +51 -0
  173. package/dist/core/global-config.d.ts.map +1 -0
  174. package/dist/core/global-config.js +124 -0
  175. package/dist/core/global-config.js.map +1 -0
  176. package/dist/core/id.d.ts +17 -0
  177. package/dist/core/id.d.ts.map +1 -0
  178. package/dist/core/id.js +30 -0
  179. package/dist/core/id.js.map +1 -0
  180. package/dist/core/init.d.ts +34 -0
  181. package/dist/core/init.d.ts.map +1 -0
  182. package/dist/core/init.js +495 -0
  183. package/dist/core/init.js.map +1 -0
  184. package/dist/core/list.d.ts +12 -0
  185. package/dist/core/list.d.ts.map +1 -0
  186. package/dist/core/list.js +192 -0
  187. package/dist/core/list.js.map +1 -0
  188. package/dist/core/migrate.d.ts +52 -0
  189. package/dist/core/migrate.d.ts.map +1 -0
  190. package/dist/core/migrate.js +300 -0
  191. package/dist/core/migrate.js.map +1 -0
  192. package/dist/core/parsers/change-parser.d.ts +19 -0
  193. package/dist/core/parsers/change-parser.d.ts.map +1 -0
  194. package/dist/core/parsers/change-parser.js +204 -0
  195. package/dist/core/parsers/change-parser.js.map +1 -0
  196. package/dist/core/parsers/markdown-parser.d.ts +29 -0
  197. package/dist/core/parsers/markdown-parser.d.ts.map +1 -0
  198. package/dist/core/parsers/markdown-parser.js +181 -0
  199. package/dist/core/parsers/markdown-parser.js.map +1 -0
  200. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  201. package/dist/core/parsers/requirement-blocks.d.ts.map +1 -0
  202. package/dist/core/parsers/requirement-blocks.js +201 -0
  203. package/dist/core/parsers/requirement-blocks.js.map +1 -0
  204. package/dist/core/parsers/requirement-text.d.ts +55 -0
  205. package/dist/core/parsers/requirement-text.d.ts.map +1 -0
  206. package/dist/core/parsers/requirement-text.js +136 -0
  207. package/dist/core/parsers/requirement-text.js.map +1 -0
  208. package/dist/core/parsers/spec-structure.d.ts +9 -0
  209. package/dist/core/parsers/spec-structure.d.ts.map +1 -0
  210. package/dist/core/parsers/spec-structure.js +88 -0
  211. package/dist/core/parsers/spec-structure.js.map +1 -0
  212. package/dist/core/planning-home.d.ts +16 -0
  213. package/dist/core/planning-home.d.ts.map +1 -0
  214. package/dist/core/planning-home.js +67 -0
  215. package/dist/core/planning-home.js.map +1 -0
  216. package/dist/core/profiles.d.ts +24 -0
  217. package/dist/core/profiles.d.ts.map +1 -0
  218. package/dist/core/profiles.js +27 -0
  219. package/dist/core/profiles.js.map +1 -0
  220. package/dist/core/project-config.d.ts +100 -0
  221. package/dist/core/project-config.d.ts.map +1 -0
  222. package/dist/core/project-config.js +389 -0
  223. package/dist/core/project-config.js.map +1 -0
  224. package/dist/core/references.d.ts +40 -0
  225. package/dist/core/references.d.ts.map +1 -0
  226. package/dist/core/references.js +11 -0
  227. package/dist/core/references.js.map +1 -0
  228. package/dist/core/root-selection.d.ts +57 -0
  229. package/dist/core/root-selection.d.ts.map +1 -0
  230. package/dist/core/root-selection.js +98 -0
  231. package/dist/core/root-selection.js.map +1 -0
  232. package/dist/core/schemas/base.schema.d.ts +13 -0
  233. package/dist/core/schemas/base.schema.d.ts.map +1 -0
  234. package/dist/core/schemas/base.schema.js +18 -0
  235. package/dist/core/schemas/base.schema.js.map +1 -0
  236. package/dist/core/schemas/change.schema.d.ts +73 -0
  237. package/dist/core/schemas/change.schema.d.ts.map +1 -0
  238. package/dist/core/schemas/change.schema.js +31 -0
  239. package/dist/core/schemas/change.schema.js.map +1 -0
  240. package/dist/core/schemas/index.d.ts +4 -0
  241. package/dist/core/schemas/index.d.ts.map +1 -0
  242. package/dist/core/schemas/index.js +4 -0
  243. package/dist/core/schemas/index.js.map +1 -0
  244. package/dist/core/schemas/spec.schema.d.ts +18 -0
  245. package/dist/core/schemas/spec.schema.d.ts.map +1 -0
  246. package/dist/core/schemas/spec.schema.js +15 -0
  247. package/dist/core/schemas/spec.schema.js.map +1 -0
  248. package/dist/core/shared/index.d.ts +8 -0
  249. package/dist/core/shared/index.d.ts.map +1 -0
  250. package/dist/core/shared/index.js +8 -0
  251. package/dist/core/shared/index.js.map +1 -0
  252. package/dist/core/shared/skill-generation.d.ts +63 -0
  253. package/dist/core/shared/skill-generation.d.ts.map +1 -0
  254. package/dist/core/shared/skill-generation.js +125 -0
  255. package/dist/core/shared/skill-generation.js.map +1 -0
  256. package/dist/core/shared/tool-detection.d.ts +96 -0
  257. package/dist/core/shared/tool-detection.d.ts.map +1 -0
  258. package/dist/core/shared/tool-detection.js +207 -0
  259. package/dist/core/shared/tool-detection.js.map +1 -0
  260. package/dist/core/spec-presenter.d.ts +17 -0
  261. package/dist/core/spec-presenter.d.ts.map +1 -0
  262. package/dist/core/spec-presenter.js +98 -0
  263. package/dist/core/spec-presenter.js.map +1 -0
  264. package/dist/core/specs-apply.d.ts +78 -0
  265. package/dist/core/specs-apply.d.ts.map +1 -0
  266. package/dist/core/specs-apply.js +429 -0
  267. package/dist/core/specs-apply.js.map +1 -0
  268. package/dist/core/templates/index.d.ts +8 -0
  269. package/dist/core/templates/index.d.ts.map +1 -0
  270. package/dist/core/templates/index.js +9 -0
  271. package/dist/core/templates/index.js.map +1 -0
  272. package/dist/core/templates/skill-templates.d.ts +14 -0
  273. package/dist/core/templates/skill-templates.d.ts.map +1 -0
  274. package/dist/core/templates/skill-templates.js +13 -0
  275. package/dist/core/templates/skill-templates.js.map +1 -0
  276. package/dist/core/templates/types.d.ts +20 -0
  277. package/dist/core/templates/types.d.ts.map +1 -0
  278. package/dist/core/templates/types.js +5 -0
  279. package/dist/core/templates/types.js.map +1 -0
  280. package/dist/core/templates/workflows/apply.d.ts +10 -0
  281. package/dist/core/templates/workflows/apply.d.ts.map +1 -0
  282. package/dist/core/templates/workflows/apply.js +81 -0
  283. package/dist/core/templates/workflows/apply.js.map +1 -0
  284. package/dist/core/templates/workflows/archive.d.ts +10 -0
  285. package/dist/core/templates/workflows/archive.d.ts.map +1 -0
  286. package/dist/core/templates/workflows/archive.js +75 -0
  287. package/dist/core/templates/workflows/archive.js.map +1 -0
  288. package/dist/core/templates/workflows/explore.d.ts +10 -0
  289. package/dist/core/templates/workflows/explore.d.ts.map +1 -0
  290. package/dist/core/templates/workflows/explore.js +75 -0
  291. package/dist/core/templates/workflows/explore.js.map +1 -0
  292. package/dist/core/templates/workflows/issue.d.ts +10 -0
  293. package/dist/core/templates/workflows/issue.d.ts.map +1 -0
  294. package/dist/core/templates/workflows/issue.js +89 -0
  295. package/dist/core/templates/workflows/issue.js.map +1 -0
  296. package/dist/core/templates/workflows/propose.d.ts +10 -0
  297. package/dist/core/templates/workflows/propose.d.ts.map +1 -0
  298. package/dist/core/templates/workflows/propose.js +77 -0
  299. package/dist/core/templates/workflows/propose.js.map +1 -0
  300. package/dist/core/templates/workflows/sync.d.ts +14 -0
  301. package/dist/core/templates/workflows/sync.d.ts.map +1 -0
  302. package/dist/core/templates/workflows/sync.js +86 -0
  303. package/dist/core/templates/workflows/sync.js.map +1 -0
  304. package/dist/core/templates/workflows/update.d.ts +10 -0
  305. package/dist/core/templates/workflows/update.d.ts.map +1 -0
  306. package/dist/core/templates/workflows/update.js +99 -0
  307. package/dist/core/templates/workflows/update.js.map +1 -0
  308. package/dist/core/templates/workflows/verify.d.ts +9 -0
  309. package/dist/core/templates/workflows/verify.d.ts.map +1 -0
  310. package/dist/core/templates/workflows/verify.js +44 -0
  311. package/dist/core/templates/workflows/verify.js.map +1 -0
  312. package/dist/core/update.d.ts +46 -0
  313. package/dist/core/update.d.ts.map +1 -0
  314. package/dist/core/update.js +296 -0
  315. package/dist/core/update.js.map +1 -0
  316. package/dist/core/validation/constants.d.ts +34 -0
  317. package/dist/core/validation/constants.d.ts.map +1 -0
  318. package/dist/core/validation/constants.js +40 -0
  319. package/dist/core/validation/constants.js.map +1 -0
  320. package/dist/core/validation/section-validator.d.ts +19 -0
  321. package/dist/core/validation/section-validator.d.ts.map +1 -0
  322. package/dist/core/validation/section-validator.js +59 -0
  323. package/dist/core/validation/section-validator.js.map +1 -0
  324. package/dist/core/validation/types.d.ts +18 -0
  325. package/dist/core/validation/types.d.ts.map +1 -0
  326. package/dist/core/validation/types.js +2 -0
  327. package/dist/core/validation/types.js.map +1 -0
  328. package/dist/core/validation/validator.d.ts +51 -0
  329. package/dist/core/validation/validator.d.ts.map +1 -0
  330. package/dist/core/validation/validator.js +469 -0
  331. package/dist/core/validation/validator.js.map +1 -0
  332. package/dist/index.d.ts +2 -0
  333. package/dist/index.d.ts.map +1 -0
  334. package/dist/index.js +2 -0
  335. package/dist/index.js.map +1 -0
  336. package/dist/prompts/searchable-multi-select.d.ts +28 -0
  337. package/dist/prompts/searchable-multi-select.d.ts.map +1 -0
  338. package/dist/prompts/searchable-multi-select.js +158 -0
  339. package/dist/prompts/searchable-multi-select.js.map +1 -0
  340. package/dist/ui/welcome-screen.d.ts +5 -0
  341. package/dist/ui/welcome-screen.d.ts.map +1 -0
  342. package/dist/ui/welcome-screen.js +22 -0
  343. package/dist/ui/welcome-screen.js.map +1 -0
  344. package/dist/utils/change-metadata.d.ts +55 -0
  345. package/dist/utils/change-metadata.d.ts.map +1 -0
  346. package/dist/utils/change-metadata.js +141 -0
  347. package/dist/utils/change-metadata.js.map +1 -0
  348. package/dist/utils/change-utils.d.ts +73 -0
  349. package/dist/utils/change-utils.d.ts.map +1 -0
  350. package/dist/utils/change-utils.js +194 -0
  351. package/dist/utils/change-utils.js.map +1 -0
  352. package/dist/utils/command-references.d.ts +18 -0
  353. package/dist/utils/command-references.d.ts.map +1 -0
  354. package/dist/utils/command-references.js +20 -0
  355. package/dist/utils/command-references.js.map +1 -0
  356. package/dist/utils/file-system.d.ts +41 -0
  357. package/dist/utils/file-system.d.ts.map +1 -0
  358. package/dist/utils/file-system.js +320 -0
  359. package/dist/utils/file-system.js.map +1 -0
  360. package/dist/utils/index.d.ts +6 -0
  361. package/dist/utils/index.d.ts.map +1 -0
  362. package/dist/utils/index.js +9 -0
  363. package/dist/utils/index.js.map +1 -0
  364. package/dist/utils/interactive.d.ts +18 -0
  365. package/dist/utils/interactive.d.ts.map +1 -0
  366. package/dist/utils/interactive.js +21 -0
  367. package/dist/utils/interactive.js.map +1 -0
  368. package/dist/utils/item-discovery.d.ts +14 -0
  369. package/dist/utils/item-discovery.d.ts.map +1 -0
  370. package/dist/utils/item-discovery.js +104 -0
  371. package/dist/utils/item-discovery.js.map +1 -0
  372. package/dist/utils/link.d.ts +22 -0
  373. package/dist/utils/link.d.ts.map +1 -0
  374. package/dist/utils/link.js +85 -0
  375. package/dist/utils/link.js.map +1 -0
  376. package/dist/utils/match.d.ts +3 -0
  377. package/dist/utils/match.d.ts.map +1 -0
  378. package/dist/utils/match.js +22 -0
  379. package/dist/utils/match.js.map +1 -0
  380. package/dist/utils/shell-detection.d.ts +20 -0
  381. package/dist/utils/shell-detection.d.ts.map +1 -0
  382. package/dist/utils/shell-detection.js +41 -0
  383. package/dist/utils/shell-detection.js.map +1 -0
  384. package/dist/utils/task-progress.d.ts +32 -0
  385. package/dist/utils/task-progress.d.ts.map +1 -0
  386. package/dist/utils/task-progress.js +129 -0
  387. package/dist/utils/task-progress.js.map +1 -0
  388. package/dist/utils/timestamp.d.ts +9 -0
  389. package/dist/utils/timestamp.d.ts.map +1 -0
  390. package/dist/utils/timestamp.js +18 -0
  391. package/dist/utils/timestamp.js.map +1 -0
  392. package/package.json +55 -0
  393. package/schemas/issue/schema.yaml +34 -0
  394. package/schemas/issue/templates/spec.md +13 -0
  395. package/schemas/issue/templates/task.md +21 -0
  396. package/schemas/issue/templates/ticket.md +2 -0
  397. package/schemas/sdd/schema.yaml +55 -0
  398. package/schemas/sdd/templates/design.md +15 -0
  399. package/schemas/sdd/templates/proposal.md +15 -0
  400. package/schemas/sdd/templates/spec.md +13 -0
  401. package/schemas/sdd/templates/tasks.md +11 -0
  402. package/schemas/sdd/templates/ticket.md +2 -0
@@ -0,0 +1,164 @@
1
+ import { isInteractive } from '../utils/interactive.js';
2
+ import { getActiveChangeIds, getSpecIds } from '../utils/item-discovery.js';
3
+ import { resolveRootForCommand, toRootOutput, } from '../core/root-selection.js';
4
+ import { ChangePresenter } from '../core/change-presenter.js';
5
+ import { SpecPresenter } from '../core/spec-presenter.js';
6
+ import { nearestMatches } from '../utils/match.js';
7
+ const CHANGE_FLAG_KEYS = new Set(['deltasOnly', 'requirementsOnly']);
8
+ const SPEC_FLAG_KEYS = new Set(['requirements', 'scenarios', 'requirement']);
9
+ export class ShowCommand {
10
+ async execute(itemName, options = {}) {
11
+ const root = await resolveRootForCommand(options, { json: options.json });
12
+ if (!root) {
13
+ return;
14
+ }
15
+ const interactive = isInteractive(options);
16
+ const typeOverride = this.normalizeType(options.type);
17
+ if (!itemName) {
18
+ if (interactive) {
19
+ const { select } = await import('@inquirer/prompts');
20
+ const type = await select({
21
+ message: 'What would you like to show?',
22
+ choices: [
23
+ { name: 'Change', value: 'change' },
24
+ { name: 'Spec', value: 'spec' },
25
+ ],
26
+ });
27
+ await this.runInteractiveByType(type, options, root);
28
+ return;
29
+ }
30
+ this.printNonInteractiveHint(root);
31
+ process.exitCode = 1;
32
+ return;
33
+ }
34
+ await this.showDirect(itemName, { typeOverride, options, root });
35
+ }
36
+ normalizeType(value) {
37
+ if (!value)
38
+ return undefined;
39
+ const v = value.toLowerCase();
40
+ if (v === 'change' || v === 'spec')
41
+ return v;
42
+ return undefined;
43
+ }
44
+ delegateOptions(root, options) {
45
+ return {
46
+ ...options,
47
+ ...(options.json ? { rootOutput: toRootOutput(root) } : {}),
48
+ };
49
+ }
50
+ async runInteractiveByType(type, options, root) {
51
+ const { select } = await import('@inquirer/prompts');
52
+ if (type === 'change') {
53
+ const changes = await getActiveChangeIds(root.path);
54
+ if (changes.length === 0) {
55
+ console.error('No changes found.');
56
+ process.exitCode = 1;
57
+ return;
58
+ }
59
+ const picked = await select({ message: 'Pick a change', choices: changes.map(id => ({ name: id, value: id })) });
60
+ const cmd = new ChangePresenter(root.path);
61
+ await cmd.show(picked, this.delegateOptions(root, options));
62
+ return;
63
+ }
64
+ const specs = await getSpecIds(root.path);
65
+ if (specs.length === 0) {
66
+ console.error('No specs found.');
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+ const picked = await select({ message: 'Pick a spec', choices: specs.map(id => ({ name: id, value: id })) });
71
+ const cmd = new SpecPresenter(root.path);
72
+ await cmd.show(picked, this.delegateOptions(root, options));
73
+ }
74
+ async showDirect(itemName, params) {
75
+ const root = params.root;
76
+ // Optimize lookups when type is pre-specified
77
+ let isChange = false;
78
+ let isSpec = false;
79
+ let changes = [];
80
+ let specs = [];
81
+ if (params.typeOverride === 'change') {
82
+ changes = await getActiveChangeIds(root.path);
83
+ isChange = changes.includes(itemName);
84
+ }
85
+ else if (params.typeOverride === 'spec') {
86
+ specs = await getSpecIds(root.path);
87
+ isSpec = specs.includes(itemName);
88
+ }
89
+ else {
90
+ [changes, specs] = await Promise.all([getActiveChangeIds(root.path), getSpecIds(root.path)]);
91
+ isChange = changes.includes(itemName);
92
+ isSpec = specs.includes(itemName);
93
+ }
94
+ const resolvedType = params.typeOverride ?? (isChange ? 'change' : isSpec ? 'spec' : undefined);
95
+ if (!resolvedType) {
96
+ const suggestions = nearestMatches(itemName, [...changes, ...specs]);
97
+ const message = suggestions.length
98
+ ? `Unknown item '${itemName}'. Did you mean: ${suggestions.join(', ')}?`
99
+ : `Unknown item '${itemName}'.`;
100
+ if (params.options.json) {
101
+ console.log(JSON.stringify({ status: [{ severity: 'error', code: 'unknown_item', message }] }, null, 2));
102
+ }
103
+ else {
104
+ console.error(message);
105
+ }
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+ if (!params.typeOverride && isChange && isSpec) {
110
+ if (params.options.json) {
111
+ console.log(JSON.stringify({
112
+ status: [
113
+ {
114
+ severity: 'error',
115
+ code: 'ambiguous_item',
116
+ message: `Ambiguous item '${itemName}' matches both a change and a spec.`,
117
+ fix: 'Pass --type change|spec.',
118
+ },
119
+ ],
120
+ }, null, 2));
121
+ process.exitCode = 1;
122
+ return;
123
+ }
124
+ console.error(`Ambiguous item '${itemName}' matches both a change and a spec.`);
125
+ console.error('Pass --type change|spec, or use: tospec show <item> --type change / --type spec');
126
+ process.exitCode = 1;
127
+ return;
128
+ }
129
+ this.warnIrrelevantFlags(resolvedType, params.options);
130
+ if (resolvedType === 'change') {
131
+ const cmd = new ChangePresenter(root.path);
132
+ await cmd.show(itemName, this.delegateOptions(root, params.options));
133
+ return;
134
+ }
135
+ const cmd = new SpecPresenter(root.path);
136
+ await cmd.show(itemName, this.delegateOptions(root, params.options));
137
+ }
138
+ printNonInteractiveHint(root) {
139
+ console.error('Nothing to show. Try one of:');
140
+ console.error(' tospec show <item>');
141
+ console.error(' tospec show <item> --type change');
142
+ console.error(' tospec show <item> --type spec');
143
+ console.error('Or run in an interactive terminal.');
144
+ }
145
+ warnIrrelevantFlags(type, options) {
146
+ const irrelevant = [];
147
+ if (type === 'change') {
148
+ for (const k of SPEC_FLAG_KEYS)
149
+ if (k in options)
150
+ irrelevant.push(k);
151
+ }
152
+ else {
153
+ for (const k of CHANGE_FLAG_KEYS)
154
+ if (k in options)
155
+ irrelevant.push(k);
156
+ }
157
+ if (irrelevant.length > 0) {
158
+ console.error(`Warning: Ignoring flags not applicable to ${type}: ${irrelevant.join(', ')}`);
159
+ return true;
160
+ }
161
+ return false;
162
+ }
163
+ }
164
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { ValidationIssue, ValidationReport } from '../core/validation/types.js';
2
+ interface ExecuteOptions {
3
+ all?: boolean;
4
+ changes?: boolean;
5
+ specs?: boolean;
6
+ type?: string;
7
+ strict?: boolean;
8
+ json?: boolean;
9
+ noInteractive?: boolean;
10
+ interactive?: boolean;
11
+ concurrency?: string;
12
+ }
13
+ export declare class ValidateCommand {
14
+ execute(itemName: string | undefined, options?: ExecuteOptions): Promise<void>;
15
+ private normalizeType;
16
+ /**
17
+ * Resolve change IDs by directory existence within the resolved root — the
18
+ * same rule `tospec status`/`instructions` use (`getAvailableChanges`) —
19
+ * rather than requiring `proposal.md`. This lets `validate` resolve a
20
+ * scaffolded or still-authoring change that the sibling commands already
21
+ * resolve (#1182). Sorted to preserve the prior `getActiveChangeIds` ordering.
22
+ */
23
+ private listChangeIds;
24
+ private runInteractiveSelector;
25
+ private printNonInteractiveHint;
26
+ private validateDirectItem;
27
+ private validateByType;
28
+ private printReport;
29
+ private printNextSteps;
30
+ private runBulkValidation;
31
+ }
32
+ /**
33
+ * Validates schema-declared `requiredSections` for ticket/design/task-style
34
+ * artifacts that have no Requirement grammar of their own. Only artifacts
35
+ * that (a) declare a `validation` block and (b) already have an output file
36
+ * on disk are checked — artifacts not yet produced are `status`'s concern,
37
+ * not validate's.
38
+ */
39
+ export declare function validateArtifactSections(projectRoot: string, changeDir: string): Promise<ValidationIssue[]>;
40
+ /**
41
+ * Whether a change's schema requires at least one delta spec. False only
42
+ * when the schema declares `specs` as `optional` and this change produced
43
+ * none — a pure fix with no behavioral change (e.g. an issue schema change)
44
+ * is a legitimate, complete change, not a validation failure. Falls back to
45
+ * requiring deltas (the stricter, pre-existing behavior) when the schema
46
+ * can't be resolved.
47
+ */
48
+ export declare function deltaSpecsRequired(projectRoot: string, changeDir: string): Promise<boolean>;
49
+ export declare function mergeSectionIssues(report: ValidationReport, extra: ValidationIssue[], strict: boolean): ValidationReport;
50
+ export {};
51
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAkBrF,UAAU,cAAc;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAUD,qBAAa,eAAe;IACpB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCxF,OAAO,CAAC,aAAa;IAOrB;;;;;;OAMG;YACW,aAAa;YAKb,sBAAsB;IA8BpC,OAAO,CAAC,uBAAuB;YASjB,kBAAkB;YAyDlB,cAAc;IAyB5B,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,cAAc;YAeR,iBAAiB;CA0HhC;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA6BjH;AAID;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcjG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAQxH"}
@@ -0,0 +1,416 @@
1
+ import path from 'path';
2
+ import { promises as fs } from 'fs';
3
+ import { Validator } from '../core/validation/validator.js';
4
+ import { validateSections } from '../core/validation/section-validator.js';
5
+ import { resolveSchema, getSchemaDir } from '../core/artifact-graph/resolver.js';
6
+ import { resolveArtifactOutputs } from '../core/artifact-graph/outputs.js';
7
+ import { resolveSchemaForChange } from '../utils/change-metadata.js';
8
+ import { FileSystemUtils } from '../utils/file-system.js';
9
+ import { resolveRootForCommand, toRootOutput, } from '../core/root-selection.js';
10
+ import { isInteractive, resolveNoInteractive } from '../utils/interactive.js';
11
+ import { getSpecIds } from '../utils/item-discovery.js';
12
+ import { getAvailableChanges } from './workflow/shared.js';
13
+ import { nearestMatches } from '../utils/match.js';
14
+ export class ValidateCommand {
15
+ async execute(itemName, options = {}) {
16
+ const root = await resolveRootForCommand(options, { json: options.json });
17
+ if (!root) {
18
+ return;
19
+ }
20
+ const interactive = isInteractive(options);
21
+ // Handle bulk flags first
22
+ if (options.all || options.changes || options.specs) {
23
+ await this.runBulkValidation(root, {
24
+ changes: !!options.all || !!options.changes,
25
+ specs: !!options.all || !!options.specs,
26
+ }, { strict: !!options.strict, json: !!options.json, concurrency: options.concurrency, noInteractive: resolveNoInteractive(options) });
27
+ return;
28
+ }
29
+ // No item and no flags
30
+ if (!itemName) {
31
+ if (interactive) {
32
+ await this.runInteractiveSelector(root, { strict: !!options.strict, json: !!options.json, concurrency: options.concurrency });
33
+ return;
34
+ }
35
+ this.printNonInteractiveHint(root);
36
+ process.exitCode = 1;
37
+ return;
38
+ }
39
+ // Direct item validation with type detection or override
40
+ const typeOverride = this.normalizeType(options.type);
41
+ await this.validateDirectItem(root, itemName, { typeOverride, strict: !!options.strict, json: !!options.json });
42
+ }
43
+ normalizeType(value) {
44
+ if (!value)
45
+ return undefined;
46
+ const v = value.toLowerCase();
47
+ if (v === 'change' || v === 'spec')
48
+ return v;
49
+ return undefined;
50
+ }
51
+ /**
52
+ * Resolve change IDs by directory existence within the resolved root — the
53
+ * same rule `tospec status`/`instructions` use (`getAvailableChanges`) —
54
+ * rather than requiring `proposal.md`. This lets `validate` resolve a
55
+ * scaffolded or still-authoring change that the sibling commands already
56
+ * resolve (#1182). Sorted to preserve the prior `getActiveChangeIds` ordering.
57
+ */
58
+ async listChangeIds(root) {
59
+ const ids = await getAvailableChanges(root.path, root.changesDir);
60
+ return ids.sort();
61
+ }
62
+ async runInteractiveSelector(root, opts) {
63
+ const { select } = await import('@inquirer/prompts');
64
+ const choice = await select({
65
+ message: 'What would you like to validate?',
66
+ choices: [
67
+ { name: 'All (changes + specs)', value: 'all' },
68
+ { name: 'All changes', value: 'changes' },
69
+ { name: 'All specs', value: 'specs' },
70
+ { name: 'Pick a specific change or spec', value: 'one' },
71
+ ],
72
+ });
73
+ if (choice === 'all')
74
+ return this.runBulkValidation(root, { changes: true, specs: true }, opts);
75
+ if (choice === 'changes')
76
+ return this.runBulkValidation(root, { changes: true, specs: false }, opts);
77
+ if (choice === 'specs')
78
+ return this.runBulkValidation(root, { changes: false, specs: true }, opts);
79
+ // one
80
+ const [changes, specs] = await Promise.all([this.listChangeIds(root), getSpecIds(root.path)]);
81
+ const items = [];
82
+ items.push(...changes.map(id => ({ name: `change/${id}`, value: { type: 'change', id } })));
83
+ items.push(...specs.map(id => ({ name: `spec/${id}`, value: { type: 'spec', id } })));
84
+ if (items.length === 0) {
85
+ console.error('No items found to validate.');
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ const picked = await select({ message: 'Pick an item', choices: items });
90
+ await this.validateByType(root, picked.type, picked.id, opts);
91
+ }
92
+ printNonInteractiveHint(root) {
93
+ console.error('Nothing to validate. Try one of:');
94
+ console.error(` ${'tospec validate --all'}`);
95
+ console.error(` ${'tospec validate --changes'}`);
96
+ console.error(` ${'tospec validate --specs'}`);
97
+ console.error(` ${'tospec validate <item-name>'}`);
98
+ console.error('Or run in an interactive terminal.');
99
+ }
100
+ async validateDirectItem(root, itemName, opts) {
101
+ const [changes, specs] = await Promise.all([this.listChangeIds(root), getSpecIds(root.path)]);
102
+ const isChange = changes.includes(itemName);
103
+ const isSpec = specs.includes(itemName);
104
+ const type = opts.typeOverride ?? (isChange ? 'change' : isSpec ? 'spec' : undefined);
105
+ if (!type) {
106
+ const suggestions = nearestMatches(itemName, [...changes, ...specs]);
107
+ const message = suggestions.length
108
+ ? `Unknown item '${itemName}'. Did you mean: ${suggestions.join(', ')}?`
109
+ : `Unknown item '${itemName}'.`;
110
+ if (opts.json) {
111
+ console.log(JSON.stringify({ status: [{ severity: 'error', code: 'unknown_item', message }] }, null, 2));
112
+ }
113
+ else {
114
+ console.error(message);
115
+ }
116
+ process.exitCode = 1;
117
+ return;
118
+ }
119
+ if (!opts.typeOverride && isChange && isSpec) {
120
+ if (opts.json) {
121
+ console.log(JSON.stringify({
122
+ status: [
123
+ {
124
+ severity: 'error',
125
+ code: 'ambiguous_item',
126
+ message: `Ambiguous item '${itemName}' matches both a change and a spec.`,
127
+ fix: 'Pass --type change|spec.',
128
+ },
129
+ ],
130
+ }, null, 2));
131
+ process.exitCode = 1;
132
+ return;
133
+ }
134
+ console.error(`Ambiguous item '${itemName}' matches both a change and a spec.`);
135
+ console.error('Pass --type change|spec, or use: tospec validate --changes / tospec validate --specs');
136
+ process.exitCode = 1;
137
+ return;
138
+ }
139
+ await this.validateByType(root, type, itemName, opts);
140
+ }
141
+ async validateByType(root, type, id, opts) {
142
+ const validator = new Validator(opts.strict);
143
+ if (type === 'change') {
144
+ const changeDir = path.join(root.changesDir, id);
145
+ const start = Date.now();
146
+ const requireDeltas = await deltaSpecsRequired(root.path, changeDir);
147
+ const [deltaReport, sectionIssues] = await Promise.all([
148
+ requireDeltas ? validator.validateChangeDeltaSpecs(changeDir) : Promise.resolve(EMPTY_REPORT),
149
+ validateArtifactSections(root.path, changeDir),
150
+ ]);
151
+ const report = mergeSectionIssues(deltaReport, sectionIssues, opts.strict);
152
+ const durationMs = Date.now() - start;
153
+ this.printReport('change', id, report, durationMs, opts.json, root);
154
+ // Non-zero exit if invalid (keeps enriched output test semantics)
155
+ process.exitCode = report.valid ? 0 : 1;
156
+ return;
157
+ }
158
+ const file = path.join(root.specsDir, id, 'spec.md');
159
+ const start = Date.now();
160
+ const report = await validator.validateSpec(file);
161
+ const durationMs = Date.now() - start;
162
+ this.printReport('spec', id, report, durationMs, opts.json, root);
163
+ process.exitCode = report.valid ? 0 : 1;
164
+ }
165
+ printReport(type, id, report, durationMs, json, root) {
166
+ if (json) {
167
+ const out = { items: [{ id, type, valid: report.valid, issues: report.issues, durationMs }], summary: { totals: { items: 1, passed: report.valid ? 1 : 0, failed: report.valid ? 0 : 1 }, byType: { [type]: { items: 1, passed: report.valid ? 1 : 0, failed: report.valid ? 0 : 1 } } }, version: '1.0', root: toRootOutput(root) };
168
+ console.log(JSON.stringify(out, null, 2));
169
+ return;
170
+ }
171
+ if (report.valid) {
172
+ console.log(`${type === 'change' ? 'Change' : 'Specification'} '${id}' is valid`);
173
+ }
174
+ else {
175
+ console.error(`${type === 'change' ? 'Change' : 'Specification'} '${id}' has issues`);
176
+ for (const issue of report.issues) {
177
+ const label = issue.level === 'ERROR' ? 'ERROR' : issue.level;
178
+ const prefix = issue.level === 'ERROR' ? '✗' : issue.level === 'WARNING' ? '⚠' : 'ℹ';
179
+ console.error(`${prefix} [${label}] ${issue.path}: ${issue.message}`);
180
+ }
181
+ this.printNextSteps(type, id, root);
182
+ }
183
+ }
184
+ printNextSteps(type, id, root) {
185
+ const bullets = [];
186
+ if (type === 'change') {
187
+ bullets.push('- Ensure change has deltas in specs/: use headers ## ADDED/MODIFIED/REMOVED/RENAMED Requirements');
188
+ bullets.push('- Each requirement MUST include at least one #### Scenario: block');
189
+ bullets.push(`- Debug parsed deltas: ${`tospec show ${id} --json --deltas-only`}`);
190
+ }
191
+ else {
192
+ bullets.push('- Ensure spec includes ## Purpose and ## Requirements sections');
193
+ bullets.push('- Each requirement MUST include at least one #### Scenario: block');
194
+ bullets.push('- Re-run with --json to see structured report');
195
+ }
196
+ console.error('Next steps:');
197
+ bullets.forEach(b => console.error(` ${b}`));
198
+ }
199
+ async runBulkValidation(root, scope, opts) {
200
+ const showProgress = !opts.json && !opts.noInteractive;
201
+ const [changeIds, specIds] = await Promise.all([
202
+ scope.changes ? this.listChangeIds(root) : Promise.resolve([]),
203
+ scope.specs ? getSpecIds(root.path) : Promise.resolve([]),
204
+ ]);
205
+ const DEFAULT_CONCURRENCY = 6;
206
+ const maxSuggestions = 5; // used by nearestMatches
207
+ const concurrency = normalizeConcurrency(opts.concurrency) ?? normalizeConcurrency(process.env.TOSPEC_CONCURRENCY) ?? DEFAULT_CONCURRENCY;
208
+ const validator = new Validator(opts.strict);
209
+ const queue = [];
210
+ for (const id of changeIds) {
211
+ queue.push(async () => {
212
+ const start = Date.now();
213
+ const changeDir = path.join(root.changesDir, id);
214
+ const requireDeltas = await deltaSpecsRequired(root.path, changeDir);
215
+ const [deltaReport, sectionIssues] = await Promise.all([
216
+ requireDeltas ? validator.validateChangeDeltaSpecs(changeDir) : Promise.resolve(EMPTY_REPORT),
217
+ validateArtifactSections(root.path, changeDir),
218
+ ]);
219
+ const report = mergeSectionIssues(deltaReport, sectionIssues, opts.strict);
220
+ const durationMs = Date.now() - start;
221
+ return { id, type: 'change', valid: report.valid, issues: report.issues, durationMs };
222
+ });
223
+ }
224
+ for (const id of specIds) {
225
+ queue.push(async () => {
226
+ const start = Date.now();
227
+ const file = path.join(root.specsDir, id, 'spec.md');
228
+ const report = await validator.validateSpec(file);
229
+ const durationMs = Date.now() - start;
230
+ return { id, type: 'spec', valid: report.valid, issues: report.issues, durationMs };
231
+ });
232
+ }
233
+ if (queue.length === 0) {
234
+ const summary = {
235
+ totals: { items: 0, passed: 0, failed: 0 },
236
+ byType: {
237
+ ...(scope.changes ? { change: { items: 0, passed: 0, failed: 0 } } : {}),
238
+ ...(scope.specs ? { spec: { items: 0, passed: 0, failed: 0 } } : {}),
239
+ },
240
+ };
241
+ if (opts.json) {
242
+ const out = { items: [], summary, version: '1.0', root: toRootOutput(root) };
243
+ console.log(JSON.stringify(out, null, 2));
244
+ }
245
+ else {
246
+ console.log('No items found to validate.');
247
+ }
248
+ process.exitCode = 0;
249
+ return;
250
+ }
251
+ if (showProgress) {
252
+ console.log(`Validating ${queue.length} item(s)...`);
253
+ }
254
+ const results = [];
255
+ let index = 0;
256
+ let running = 0;
257
+ let passed = 0;
258
+ let failed = 0;
259
+ await new Promise((resolve) => {
260
+ const next = () => {
261
+ while (running < concurrency && index < queue.length) {
262
+ const currentIndex = index++;
263
+ const task = queue[currentIndex];
264
+ running++;
265
+ task()
266
+ .then(res => {
267
+ results.push(res);
268
+ if (res.valid)
269
+ passed++;
270
+ else
271
+ failed++;
272
+ })
273
+ .catch((error) => {
274
+ const message = error?.message || 'Unknown error';
275
+ const res = { id: getPlannedId(currentIndex, changeIds, specIds) ?? 'unknown', type: getPlannedType(currentIndex, changeIds, specIds) ?? 'change', valid: false, issues: [{ level: 'ERROR', path: 'file', message }], durationMs: 0 };
276
+ results.push(res);
277
+ failed++;
278
+ })
279
+ .finally(() => {
280
+ running--;
281
+ if (index >= queue.length && running === 0)
282
+ resolve();
283
+ else
284
+ next();
285
+ });
286
+ }
287
+ };
288
+ next();
289
+ });
290
+ results.sort((a, b) => a.id.localeCompare(b.id));
291
+ const summary = {
292
+ totals: { items: results.length, passed, failed },
293
+ byType: {
294
+ ...(scope.changes ? { change: summarizeType(results, 'change') } : {}),
295
+ ...(scope.specs ? { spec: summarizeType(results, 'spec') } : {}),
296
+ },
297
+ };
298
+ if (opts.json) {
299
+ const out = { items: results, summary, version: '1.0', root: toRootOutput(root) };
300
+ console.log(JSON.stringify(out, null, 2));
301
+ }
302
+ else {
303
+ for (const res of results) {
304
+ if (res.valid)
305
+ console.log(`✓ ${res.type}/${res.id}`);
306
+ else
307
+ console.error(`✗ ${res.type}/${res.id}`);
308
+ }
309
+ console.log(`Totals: ${summary.totals.passed} passed, ${summary.totals.failed} failed (${summary.totals.items} items)`);
310
+ const firstFailure = results.find((res) => !res.valid);
311
+ if (firstFailure) {
312
+ console.log(`Details: tospec validate ${firstFailure.id} --type ${firstFailure.type}`);
313
+ }
314
+ }
315
+ process.exitCode = failed > 0 ? 1 : 0;
316
+ }
317
+ }
318
+ /**
319
+ * Validates schema-declared `requiredSections` for ticket/design/task-style
320
+ * artifacts that have no Requirement grammar of their own. Only artifacts
321
+ * that (a) declare a `validation` block and (b) already have an output file
322
+ * on disk are checked — artifacts not yet produced are `status`'s concern,
323
+ * not validate's.
324
+ */
325
+ export async function validateArtifactSections(projectRoot, changeDir) {
326
+ const issues = [];
327
+ let schemaName;
328
+ let schema;
329
+ try {
330
+ schemaName = resolveSchemaForChange(changeDir, undefined, projectRoot);
331
+ schema = resolveSchema(schemaName, projectRoot);
332
+ }
333
+ catch {
334
+ return issues;
335
+ }
336
+ const schemaDir = getSchemaDir(schemaName, projectRoot);
337
+ for (const artifact of schema.artifacts) {
338
+ if (!artifact.validation)
339
+ continue;
340
+ for (const file of resolveArtifactOutputs(changeDir, artifact.generates)) {
341
+ const content = await fs.readFile(file, 'utf-8');
342
+ const relPath = FileSystemUtils.toPosixPath(path.relative(changeDir, file));
343
+ const templateRef = schemaDir
344
+ ? FileSystemUtils.toPosixPath(path.join(path.relative(projectRoot, schemaDir), 'templates', artifact.template))
345
+ : undefined;
346
+ issues.push(...validateSections(content, artifact.validation, { path: relPath, templateRef }));
347
+ }
348
+ }
349
+ return issues;
350
+ }
351
+ const EMPTY_REPORT = { valid: true, issues: [], summary: { errors: 0, warnings: 0, info: 0 } };
352
+ /**
353
+ * Whether a change's schema requires at least one delta spec. False only
354
+ * when the schema declares `specs` as `optional` and this change produced
355
+ * none — a pure fix with no behavioral change (e.g. an issue schema change)
356
+ * is a legitimate, complete change, not a validation failure. Falls back to
357
+ * requiring deltas (the stricter, pre-existing behavior) when the schema
358
+ * can't be resolved.
359
+ */
360
+ export async function deltaSpecsRequired(projectRoot, changeDir) {
361
+ let schemaName;
362
+ let schema;
363
+ try {
364
+ schemaName = resolveSchemaForChange(changeDir, undefined, projectRoot);
365
+ schema = resolveSchema(schemaName, projectRoot);
366
+ }
367
+ catch {
368
+ return true;
369
+ }
370
+ const specsArtifact = schema.artifacts.find((a) => a.id === 'specs');
371
+ if (!specsArtifact?.optional)
372
+ return true;
373
+ return resolveArtifactOutputs(changeDir, specsArtifact.generates).length > 0;
374
+ }
375
+ export function mergeSectionIssues(report, extra, strict) {
376
+ if (extra.length === 0)
377
+ return report;
378
+ const issues = [...report.issues, ...extra];
379
+ const errors = issues.filter(i => i.level === 'ERROR').length;
380
+ const warnings = issues.filter(i => i.level === 'WARNING').length;
381
+ const info = issues.filter(i => i.level === 'INFO').length;
382
+ const valid = strict ? errors === 0 && warnings === 0 : errors === 0;
383
+ return { valid, issues, summary: { errors, warnings, info } };
384
+ }
385
+ function summarizeType(results, type) {
386
+ const filtered = results.filter(r => r.type === type);
387
+ const items = filtered.length;
388
+ const passed = filtered.filter(r => r.valid).length;
389
+ const failed = items - passed;
390
+ return { items, passed, failed };
391
+ }
392
+ function normalizeConcurrency(value) {
393
+ if (!value)
394
+ return undefined;
395
+ const n = parseInt(value, 10);
396
+ if (Number.isNaN(n) || n <= 0)
397
+ return undefined;
398
+ return n;
399
+ }
400
+ function getPlannedId(index, changeIds, specIds) {
401
+ const totalChanges = changeIds.length;
402
+ if (index < totalChanges)
403
+ return changeIds[index];
404
+ const specIndex = index - totalChanges;
405
+ return specIds[specIndex];
406
+ }
407
+ function getPlannedType(index, changeIds, specIds) {
408
+ const totalChanges = changeIds.length;
409
+ if (index < totalChanges)
410
+ return 'change';
411
+ const specIndex = index - totalChanges;
412
+ if (specIndex >= 0 && specIndex < specIds.length)
413
+ return 'spec';
414
+ return undefined;
415
+ }
416
+ //# sourceMappingURL=validate.js.map