@seanmars/tospec 0.19.0-beta.7 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/CHANGELOG.md +60 -231
  2. package/README.md +69 -82
  3. package/assets/dashboard/app.js +14 -3
  4. package/assets/dashboard/style.css +7 -0
  5. package/assets/rules/tospec/decision.md +3 -0
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +227 -86
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/commands/config.d.ts +9 -17
  10. package/dist/commands/config.d.ts.map +1 -1
  11. package/dist/commands/config.js +366 -107
  12. package/dist/commands/config.js.map +1 -1
  13. package/dist/commands/dashboard.d.ts +57 -99
  14. package/dist/commands/dashboard.d.ts.map +1 -1
  15. package/dist/commands/dashboard.js +224 -282
  16. package/dist/commands/dashboard.js.map +1 -1
  17. package/dist/commands/decision.d.ts +41 -19
  18. package/dist/commands/decision.d.ts.map +1 -1
  19. package/dist/commands/decision.js +385 -79
  20. package/dist/commands/decision.js.map +1 -1
  21. package/dist/commands/metrics.d.ts +28 -51
  22. package/dist/commands/metrics.d.ts.map +1 -1
  23. package/dist/commands/metrics.js +62 -93
  24. package/dist/commands/metrics.js.map +1 -1
  25. package/dist/commands/shared-output.d.ts +18 -21
  26. package/dist/commands/shared-output.d.ts.map +1 -1
  27. package/dist/commands/shared-output.js +49 -23
  28. package/dist/commands/shared-output.js.map +1 -1
  29. package/dist/commands/show.d.ts +7 -0
  30. package/dist/commands/show.d.ts.map +1 -1
  31. package/dist/commands/show.js +29 -7
  32. package/dist/commands/show.js.map +1 -1
  33. package/dist/commands/validate.d.ts +43 -45
  34. package/dist/commands/validate.d.ts.map +1 -1
  35. package/dist/commands/validate.js +262 -129
  36. package/dist/commands/validate.js.map +1 -1
  37. package/dist/commands/workflow/index.d.ts +6 -10
  38. package/dist/commands/workflow/index.d.ts.map +1 -1
  39. package/dist/commands/workflow/index.js +6 -10
  40. package/dist/commands/workflow/index.js.map +1 -1
  41. package/dist/commands/workflow/instructions.d.ts +21 -8
  42. package/dist/commands/workflow/instructions.d.ts.map +1 -1
  43. package/dist/commands/workflow/instructions.js +254 -95
  44. package/dist/commands/workflow/instructions.js.map +1 -1
  45. package/dist/commands/workflow/new-change.d.ts +4 -5
  46. package/dist/commands/workflow/new-change.d.ts.map +1 -1
  47. package/dist/commands/workflow/new-change.js +90 -25
  48. package/dist/commands/workflow/new-change.js.map +1 -1
  49. package/dist/commands/workflow/schemas.d.ts +3 -5
  50. package/dist/commands/workflow/schemas.d.ts.map +1 -1
  51. package/dist/commands/workflow/schemas.js +37 -11
  52. package/dist/commands/workflow/schemas.js.map +1 -1
  53. package/dist/commands/workflow/shared.d.ts +48 -21
  54. package/dist/commands/workflow/shared.d.ts.map +1 -1
  55. package/dist/commands/workflow/shared.js +36 -33
  56. package/dist/commands/workflow/shared.js.map +1 -1
  57. package/dist/commands/workflow/status.d.ts +10 -6
  58. package/dist/commands/workflow/status.d.ts.map +1 -1
  59. package/dist/commands/workflow/status.js +81 -42
  60. package/dist/commands/workflow/status.js.map +1 -1
  61. package/dist/commands/workflow/templates.d.ts +10 -3
  62. package/dist/commands/workflow/templates.d.ts.map +1 -1
  63. package/dist/commands/workflow/templates.js +39 -40
  64. package/dist/commands/workflow/templates.js.map +1 -1
  65. package/dist/core/archive.d.ts +26 -21
  66. package/dist/core/archive.d.ts.map +1 -1
  67. package/dist/core/archive.js +378 -235
  68. package/dist/core/archive.js.map +1 -1
  69. package/dist/core/artifact-graph/graph.d.ts +25 -42
  70. package/dist/core/artifact-graph/graph.d.ts.map +1 -1
  71. package/dist/core/artifact-graph/graph.js +45 -63
  72. package/dist/core/artifact-graph/graph.js.map +1 -1
  73. package/dist/core/artifact-graph/index.d.ts +1 -1
  74. package/dist/core/artifact-graph/index.d.ts.map +1 -1
  75. package/dist/core/artifact-graph/index.js +1 -1
  76. package/dist/core/artifact-graph/index.js.map +1 -1
  77. package/dist/core/artifact-graph/instruction-loader.d.ts +97 -103
  78. package/dist/core/artifact-graph/instruction-loader.d.ts.map +1 -1
  79. package/dist/core/artifact-graph/instruction-loader.js +146 -119
  80. package/dist/core/artifact-graph/instruction-loader.js.map +1 -1
  81. package/dist/core/artifact-graph/outputs.d.ts +9 -23
  82. package/dist/core/artifact-graph/outputs.d.ts.map +1 -1
  83. package/dist/core/artifact-graph/outputs.js +45 -38
  84. package/dist/core/artifact-graph/outputs.js.map +1 -1
  85. package/dist/core/artifact-graph/resolver.d.ts +44 -63
  86. package/dist/core/artifact-graph/resolver.d.ts.map +1 -1
  87. package/dist/core/artifact-graph/resolver.js +85 -86
  88. package/dist/core/artifact-graph/resolver.js.map +1 -1
  89. package/dist/core/artifact-graph/schema.d.ts +0 -6
  90. package/dist/core/artifact-graph/schema.d.ts.map +1 -1
  91. package/dist/core/artifact-graph/schema.js +7 -32
  92. package/dist/core/artifact-graph/schema.js.map +1 -1
  93. package/dist/core/artifact-graph/state.d.ts +1 -8
  94. package/dist/core/artifact-graph/state.d.ts.map +1 -1
  95. package/dist/core/artifact-graph/state.js +2 -17
  96. package/dist/core/artifact-graph/state.js.map +1 -1
  97. package/dist/core/artifact-graph/stub-detection.d.ts +12 -0
  98. package/dist/core/artifact-graph/stub-detection.d.ts.map +1 -0
  99. package/dist/core/artifact-graph/stub-detection.js +39 -0
  100. package/dist/core/artifact-graph/stub-detection.js.map +1 -0
  101. package/dist/core/artifact-graph/types.d.ts +4 -0
  102. package/dist/core/artifact-graph/types.d.ts.map +1 -1
  103. package/dist/core/artifact-graph/types.js +30 -10
  104. package/dist/core/artifact-graph/types.js.map +1 -1
  105. package/dist/core/available-tools.d.ts +3 -12
  106. package/dist/core/available-tools.d.ts.map +1 -1
  107. package/dist/core/available-tools.js +4 -13
  108. package/dist/core/available-tools.js.map +1 -1
  109. package/dist/core/change-metadata/schema.d.ts +1 -1
  110. package/dist/core/change-metadata/schema.d.ts.map +1 -1
  111. package/dist/core/change-metadata/schema.js +10 -7
  112. package/dist/core/change-metadata/schema.js.map +1 -1
  113. package/dist/core/change-presenter.d.ts +23 -18
  114. package/dist/core/change-presenter.d.ts.map +1 -1
  115. package/dist/core/change-presenter.js +102 -43
  116. package/dist/core/change-presenter.js.map +1 -1
  117. package/dist/core/change-status-policy.d.ts +8 -1
  118. package/dist/core/change-status-policy.d.ts.map +1 -1
  119. package/dist/core/change-status-policy.js +25 -1
  120. package/dist/core/change-status-policy.js.map +1 -1
  121. package/dist/core/codex-metrics.d.ts +25 -45
  122. package/dist/core/codex-metrics.d.ts.map +1 -1
  123. package/dist/core/codex-metrics.js +44 -88
  124. package/dist/core/codex-metrics.js.map +1 -1
  125. package/dist/core/codex-residue.d.ts +14 -15
  126. package/dist/core/codex-residue.d.ts.map +1 -1
  127. package/dist/core/codex-residue.js +18 -22
  128. package/dist/core/codex-residue.js.map +1 -1
  129. package/dist/core/command-generation/adapters/claude.d.ts +2 -9
  130. package/dist/core/command-generation/adapters/claude.d.ts.map +1 -1
  131. package/dist/core/command-generation/adapters/claude.js +2 -12
  132. package/dist/core/command-generation/adapters/claude.js.map +1 -1
  133. package/dist/core/command-generation/adapters/index.d.ts +1 -9
  134. package/dist/core/command-generation/adapters/index.d.ts.map +1 -1
  135. package/dist/core/command-generation/adapters/index.js +1 -9
  136. package/dist/core/command-generation/adapters/index.js.map +1 -1
  137. package/dist/core/command-generation/generator.d.ts +0 -17
  138. package/dist/core/command-generation/generator.d.ts.map +1 -1
  139. package/dist/core/command-generation/generator.js +0 -17
  140. package/dist/core/command-generation/generator.js.map +1 -1
  141. package/dist/core/command-generation/index.d.ts +2 -5
  142. package/dist/core/command-generation/index.d.ts.map +1 -1
  143. package/dist/core/command-generation/index.js +0 -9
  144. package/dist/core/command-generation/index.js.map +1 -1
  145. package/dist/core/command-generation/types.d.ts +10 -36
  146. package/dist/core/command-generation/types.d.ts.map +1 -1
  147. package/dist/core/command-generation/types.js +0 -6
  148. package/dist/core/command-generation/types.js.map +1 -1
  149. package/dist/core/command-generation/yaml.d.ts +3 -18
  150. package/dist/core/command-generation/yaml.d.ts.map +1 -1
  151. package/dist/core/command-generation/yaml.js +5 -23
  152. package/dist/core/command-generation/yaml.js.map +1 -1
  153. package/dist/core/config-prompts.d.ts +2 -4
  154. package/dist/core/config-prompts.d.ts.map +1 -1
  155. package/dist/core/config-prompts.js +2 -7
  156. package/dist/core/config-prompts.js.map +1 -1
  157. package/dist/core/config-schema.d.ts +8 -53
  158. package/dist/core/config-schema.d.ts.map +1 -1
  159. package/dist/core/config-schema.js +49 -62
  160. package/dist/core/config-schema.js.map +1 -1
  161. package/dist/core/config.d.ts +39 -26
  162. package/dist/core/config.d.ts.map +1 -1
  163. package/dist/core/config.js +36 -22
  164. package/dist/core/config.js.map +1 -1
  165. package/dist/core/dashboard-activity.d.ts +7 -9
  166. package/dist/core/dashboard-activity.d.ts.map +1 -1
  167. package/dist/core/dashboard-activity.js +26 -24
  168. package/dist/core/dashboard-activity.js.map +1 -1
  169. package/dist/core/dashboard-data.d.ts +40 -22
  170. package/dist/core/dashboard-data.d.ts.map +1 -1
  171. package/dist/core/dashboard-data.js +62 -70
  172. package/dist/core/dashboard-data.js.map +1 -1
  173. package/dist/core/global-config.d.ts +24 -53
  174. package/dist/core/global-config.d.ts.map +1 -1
  175. package/dist/core/global-config.js +38 -67
  176. package/dist/core/global-config.js.map +1 -1
  177. package/dist/core/init.d.ts +25 -19
  178. package/dist/core/init.d.ts.map +1 -1
  179. package/dist/core/init.js +168 -181
  180. package/dist/core/init.js.map +1 -1
  181. package/dist/core/list.d.ts +1 -1
  182. package/dist/core/list.d.ts.map +1 -1
  183. package/dist/core/list.js +121 -28
  184. package/dist/core/list.js.map +1 -1
  185. package/dist/core/local-server.d.ts +41 -83
  186. package/dist/core/local-server.d.ts.map +1 -1
  187. package/dist/core/local-server.js +53 -98
  188. package/dist/core/local-server.js.map +1 -1
  189. package/dist/core/markdown-render.d.ts +25 -0
  190. package/dist/core/markdown-render.d.ts.map +1 -0
  191. package/dist/core/markdown-render.js +94 -0
  192. package/dist/core/markdown-render.js.map +1 -0
  193. package/dist/core/migrate.d.ts +29 -14
  194. package/dist/core/migrate.d.ts.map +1 -1
  195. package/dist/core/migrate.js +184 -122
  196. package/dist/core/migrate.js.map +1 -1
  197. package/dist/core/parsers/change-parser.d.ts +7 -10
  198. package/dist/core/parsers/change-parser.d.ts.map +1 -1
  199. package/dist/core/parsers/change-parser.js +48 -56
  200. package/dist/core/parsers/change-parser.js.map +1 -1
  201. package/dist/core/parsers/markdown-parser.d.ts +8 -9
  202. package/dist/core/parsers/markdown-parser.d.ts.map +1 -1
  203. package/dist/core/parsers/markdown-parser.js +31 -22
  204. package/dist/core/parsers/markdown-parser.js.map +1 -1
  205. package/dist/core/parsers/requirement-blocks.d.ts +43 -15
  206. package/dist/core/parsers/requirement-blocks.d.ts.map +1 -1
  207. package/dist/core/parsers/requirement-blocks.js +142 -70
  208. package/dist/core/parsers/requirement-blocks.js.map +1 -1
  209. package/dist/core/parsers/requirement-text.d.ts +73 -79
  210. package/dist/core/parsers/requirement-text.d.ts.map +1 -1
  211. package/dist/core/parsers/requirement-text.js +137 -79
  212. package/dist/core/parsers/requirement-text.js.map +1 -1
  213. package/dist/core/parsers/spec-structure.d.ts.map +1 -1
  214. package/dist/core/parsers/spec-structure.js +10 -6
  215. package/dist/core/parsers/spec-structure.js.map +1 -1
  216. package/dist/core/profiles.d.ts +3 -10
  217. package/dist/core/profiles.d.ts.map +1 -1
  218. package/dist/core/profiles.js +5 -12
  219. package/dist/core/profiles.js.map +1 -1
  220. package/dist/core/project-config.d.ts +43 -44
  221. package/dist/core/project-config.d.ts.map +1 -1
  222. package/dist/core/project-config.js +107 -82
  223. package/dist/core/project-config.js.map +1 -1
  224. package/dist/core/project-layout.d.ts +9 -17
  225. package/dist/core/project-layout.d.ts.map +1 -1
  226. package/dist/core/project-layout.js +16 -26
  227. package/dist/core/project-layout.js.map +1 -1
  228. package/dist/core/root-selection.d.ts +11 -7
  229. package/dist/core/root-selection.d.ts.map +1 -1
  230. package/dist/core/root-selection.js +7 -8
  231. package/dist/core/root-selection.js.map +1 -1
  232. package/dist/core/rules.d.ts +6 -1
  233. package/dist/core/rules.d.ts.map +1 -1
  234. package/dist/core/rules.js +23 -2
  235. package/dist/core/rules.js.map +1 -1
  236. package/dist/core/schema-names.d.ts +16 -0
  237. package/dist/core/schema-names.d.ts.map +1 -0
  238. package/dist/core/schema-names.js +16 -0
  239. package/dist/core/schema-names.js.map +1 -0
  240. package/dist/core/schemas/base.schema.d.ts +3 -0
  241. package/dist/core/schemas/base.schema.d.ts.map +1 -1
  242. package/dist/core/schemas/base.schema.js +22 -6
  243. package/dist/core/schemas/base.schema.js.map +1 -1
  244. package/dist/core/schemas/change.schema.d.ts +16 -0
  245. package/dist/core/schemas/change.schema.d.ts.map +1 -1
  246. package/dist/core/schemas/change.schema.js +41 -10
  247. package/dist/core/schemas/change.schema.js.map +1 -1
  248. package/dist/core/schemas/spec.schema.d.ts +2 -0
  249. package/dist/core/schemas/spec.schema.d.ts.map +1 -1
  250. package/dist/core/shared/index.d.ts +3 -8
  251. package/dist/core/shared/index.d.ts.map +1 -1
  252. package/dist/core/shared/index.js +3 -8
  253. package/dist/core/shared/index.js.map +1 -1
  254. package/dist/core/shared/rules-generation.d.ts +19 -8
  255. package/dist/core/shared/rules-generation.d.ts.map +1 -1
  256. package/dist/core/shared/rules-generation.js +117 -50
  257. package/dist/core/shared/rules-generation.js.map +1 -1
  258. package/dist/core/shared/skill-generation.d.ts +28 -43
  259. package/dist/core/shared/skill-generation.d.ts.map +1 -1
  260. package/dist/core/shared/skill-generation.js +82 -51
  261. package/dist/core/shared/skill-generation.js.map +1 -1
  262. package/dist/core/shared/tool-detection.d.ts +39 -61
  263. package/dist/core/shared/tool-detection.d.ts.map +1 -1
  264. package/dist/core/shared/tool-detection.js +88 -80
  265. package/dist/core/shared/tool-detection.js.map +1 -1
  266. package/dist/core/skill-metrics.d.ts +36 -63
  267. package/dist/core/skill-metrics.d.ts.map +1 -1
  268. package/dist/core/skill-metrics.js +34 -73
  269. package/dist/core/skill-metrics.js.map +1 -1
  270. package/dist/core/spec-presenter.js +6 -6
  271. package/dist/core/spec-presenter.js.map +1 -1
  272. package/dist/core/specs-apply.d.ts +22 -23
  273. package/dist/core/specs-apply.d.ts.map +1 -1
  274. package/dist/core/specs-apply.js +166 -193
  275. package/dist/core/specs-apply.js.map +1 -1
  276. package/dist/core/templates/fragments/interview.d.ts +2 -6
  277. package/dist/core/templates/fragments/interview.d.ts.map +1 -1
  278. package/dist/core/templates/fragments/interview.js +2 -6
  279. package/dist/core/templates/fragments/interview.js.map +1 -1
  280. package/dist/core/templates/fragments/next-step.d.ts +4 -8
  281. package/dist/core/templates/fragments/next-step.d.ts.map +1 -1
  282. package/dist/core/templates/fragments/next-step.js +4 -8
  283. package/dist/core/templates/fragments/next-step.js.map +1 -1
  284. package/dist/core/templates/fragments/validate.d.ts +13 -0
  285. package/dist/core/templates/fragments/validate.d.ts.map +1 -0
  286. package/dist/core/templates/fragments/validate.js +13 -0
  287. package/dist/core/templates/fragments/validate.js.map +1 -0
  288. package/dist/core/templates/fragments/verify.d.ts +9 -12
  289. package/dist/core/templates/fragments/verify.d.ts.map +1 -1
  290. package/dist/core/templates/fragments/verify.js +9 -12
  291. package/dist/core/templates/fragments/verify.js.map +1 -1
  292. package/dist/core/templates/index.d.ts +0 -6
  293. package/dist/core/templates/index.d.ts.map +1 -1
  294. package/dist/core/templates/index.js +0 -7
  295. package/dist/core/templates/index.js.map +1 -1
  296. package/dist/core/templates/skill-templates.d.ts +1 -5
  297. package/dist/core/templates/skill-templates.d.ts.map +1 -1
  298. package/dist/core/templates/skill-templates.js +0 -5
  299. package/dist/core/templates/skill-templates.js.map +1 -1
  300. package/dist/core/templates/types.d.ts +3 -7
  301. package/dist/core/templates/types.d.ts.map +1 -1
  302. package/dist/core/templates/types.js +0 -3
  303. package/dist/core/templates/types.js.map +1 -1
  304. package/dist/core/templates/workflows/apply.d.ts +3 -9
  305. package/dist/core/templates/workflows/apply.d.ts.map +1 -1
  306. package/dist/core/templates/workflows/apply.js +11 -13
  307. package/dist/core/templates/workflows/apply.js.map +1 -1
  308. package/dist/core/templates/workflows/archive.d.ts +0 -6
  309. package/dist/core/templates/workflows/archive.d.ts.map +1 -1
  310. package/dist/core/templates/workflows/archive.js +19 -6
  311. package/dist/core/templates/workflows/archive.js.map +1 -1
  312. package/dist/core/templates/workflows/decision.js +4 -4
  313. package/dist/core/templates/workflows/decision.js.map +1 -1
  314. package/dist/core/templates/workflows/explore.js +1 -1
  315. package/dist/core/templates/workflows/grill.d.ts.map +1 -1
  316. package/dist/core/templates/workflows/grill.js +0 -2
  317. package/dist/core/templates/workflows/grill.js.map +1 -1
  318. package/dist/core/templates/workflows/issue.d.ts +0 -6
  319. package/dist/core/templates/workflows/issue.d.ts.map +1 -1
  320. package/dist/core/templates/workflows/issue.js +3 -2
  321. package/dist/core/templates/workflows/issue.js.map +1 -1
  322. package/dist/core/templates/workflows/propose.d.ts +0 -6
  323. package/dist/core/templates/workflows/propose.d.ts.map +1 -1
  324. package/dist/core/templates/workflows/propose.js +2 -2
  325. package/dist/core/templates/workflows/propose.js.map +1 -1
  326. package/dist/core/templates/workflows/sync.d.ts +2 -8
  327. package/dist/core/templates/workflows/sync.d.ts.map +1 -1
  328. package/dist/core/templates/workflows/sync.js +4 -3
  329. package/dist/core/templates/workflows/sync.js.map +1 -1
  330. package/dist/core/templates/workflows/update.d.ts +0 -6
  331. package/dist/core/templates/workflows/update.d.ts.map +1 -1
  332. package/dist/core/templates/workflows/update.js +9 -2
  333. package/dist/core/templates/workflows/update.js.map +1 -1
  334. package/dist/core/update.d.ts +23 -23
  335. package/dist/core/update.d.ts.map +1 -1
  336. package/dist/core/update.js +139 -118
  337. package/dist/core/update.js.map +1 -1
  338. package/dist/core/user-state-migration.d.ts +13 -15
  339. package/dist/core/user-state-migration.d.ts.map +1 -1
  340. package/dist/core/user-state-migration.js +16 -20
  341. package/dist/core/user-state-migration.js.map +1 -1
  342. package/dist/core/validation/constants.d.ts +4 -10
  343. package/dist/core/validation/constants.d.ts.map +1 -1
  344. package/dist/core/validation/constants.js +25 -20
  345. package/dist/core/validation/constants.js.map +1 -1
  346. package/dist/core/validation/prose-length.d.ts +15 -0
  347. package/dist/core/validation/prose-length.d.ts.map +1 -0
  348. package/dist/core/validation/prose-length.js +29 -0
  349. package/dist/core/validation/prose-length.js.map +1 -0
  350. package/dist/core/validation/purpose-placeholder.d.ts +9 -16
  351. package/dist/core/validation/purpose-placeholder.d.ts.map +1 -1
  352. package/dist/core/validation/purpose-placeholder.js +30 -44
  353. package/dist/core/validation/purpose-placeholder.js.map +1 -1
  354. package/dist/core/validation/section-validator.d.ts +4 -4
  355. package/dist/core/validation/section-validator.d.ts.map +1 -1
  356. package/dist/core/validation/section-validator.js +43 -7
  357. package/dist/core/validation/section-validator.js.map +1 -1
  358. package/dist/core/validation/task-numbering.d.ts +6 -3
  359. package/dist/core/validation/task-numbering.d.ts.map +1 -1
  360. package/dist/core/validation/task-numbering.js +23 -11
  361. package/dist/core/validation/task-numbering.js.map +1 -1
  362. package/dist/core/validation/types.d.ts +18 -0
  363. package/dist/core/validation/types.d.ts.map +1 -1
  364. package/dist/core/validation/types.js +12 -1
  365. package/dist/core/validation/types.js.map +1 -1
  366. package/dist/core/validation/validator.d.ts +43 -63
  367. package/dist/core/validation/validator.d.ts.map +1 -1
  368. package/dist/core/validation/validator.js +500 -267
  369. package/dist/core/validation/validator.js.map +1 -1
  370. package/dist/prompts/searchable-multi-select.d.ts +3 -8
  371. package/dist/prompts/searchable-multi-select.d.ts.map +1 -1
  372. package/dist/prompts/searchable-multi-select.js +16 -39
  373. package/dist/prompts/searchable-multi-select.js.map +1 -1
  374. package/dist/utils/change-metadata.d.ts +11 -50
  375. package/dist/utils/change-metadata.d.ts.map +1 -1
  376. package/dist/utils/change-metadata.js +48 -67
  377. package/dist/utils/change-metadata.js.map +1 -1
  378. package/dist/utils/change-utils.d.ts +30 -54
  379. package/dist/utils/change-utils.d.ts.map +1 -1
  380. package/dist/utils/change-utils.js +133 -91
  381. package/dist/utils/change-utils.js.map +1 -1
  382. package/dist/utils/file-lock.d.ts +39 -0
  383. package/dist/utils/file-lock.d.ts.map +1 -0
  384. package/dist/utils/file-lock.js +149 -0
  385. package/dist/utils/file-lock.js.map +1 -0
  386. package/dist/utils/file-system.d.ts +12 -32
  387. package/dist/utils/file-system.d.ts.map +1 -1
  388. package/dist/utils/file-system.js +16 -40
  389. package/dist/utils/file-system.js.map +1 -1
  390. package/dist/utils/frontmatter.d.ts +7 -11
  391. package/dist/utils/frontmatter.d.ts.map +1 -1
  392. package/dist/utils/frontmatter.js +11 -11
  393. package/dist/utils/frontmatter.js.map +1 -1
  394. package/dist/utils/interactive.d.ts +4 -9
  395. package/dist/utils/interactive.d.ts.map +1 -1
  396. package/dist/utils/interactive.js +2 -4
  397. package/dist/utils/interactive.js.map +1 -1
  398. package/dist/utils/item-discovery.d.ts +15 -10
  399. package/dist/utils/item-discovery.d.ts.map +1 -1
  400. package/dist/utils/item-discovery.js +42 -47
  401. package/dist/utils/item-discovery.js.map +1 -1
  402. package/dist/utils/link.d.ts +9 -18
  403. package/dist/utils/link.d.ts.map +1 -1
  404. package/dist/utils/link.js +9 -18
  405. package/dist/utils/link.js.map +1 -1
  406. package/dist/utils/requirement-diff.d.ts +13 -23
  407. package/dist/utils/requirement-diff.d.ts.map +1 -1
  408. package/dist/utils/requirement-diff.js +13 -23
  409. package/dist/utils/requirement-diff.js.map +1 -1
  410. package/dist/utils/spec-files.d.ts +7 -20
  411. package/dist/utils/spec-files.d.ts.map +1 -1
  412. package/dist/utils/spec-files.js +26 -51
  413. package/dist/utils/spec-files.js.map +1 -1
  414. package/dist/utils/task-progress.d.ts +11 -9
  415. package/dist/utils/task-progress.d.ts.map +1 -1
  416. package/dist/utils/task-progress.js +53 -32
  417. package/dist/utils/task-progress.js.map +1 -1
  418. package/dist/utils/timestamp.d.ts +5 -8
  419. package/dist/utils/timestamp.d.ts.map +1 -1
  420. package/dist/utils/timestamp.js +5 -8
  421. package/dist/utils/timestamp.js.map +1 -1
  422. package/package.json +2 -3
  423. package/schemas/decision/templates/decision.md +3 -1
  424. package/schemas/decision/templates/index.md +2 -2
  425. package/schemas/issue/schema.yaml +8 -1
  426. package/schemas/issue/templates/spec.md +27 -2
  427. package/schemas/sdd/schema.yaml +20 -1
  428. package/schemas/sdd/templates/spec.md +27 -2
  429. /package/assets/rules/tospec/{single-sourc-of-truth.md → single-source-of-truth.md} +0 -0
@@ -1,9 +1,4 @@
1
- /**
2
- * Validation threshold constants
3
- */
4
- export declare const MIN_WHY_SECTION_LENGTH = 50;
5
1
  export declare const MIN_PURPOSE_LENGTH = 50;
6
- export declare const MAX_WHY_SECTION_LENGTH = 1000;
7
2
  export declare const MAX_REQUIREMENT_TEXT_LENGTH = 500;
8
3
  export declare const MAX_DELTAS_PER_CHANGE = 10;
9
4
  export declare const PURPOSE_PLACEHOLDER_PREFIX = "TBD - created by archiving change ";
@@ -17,8 +12,6 @@ export declare const VALIDATION_MESSAGES: {
17
12
  readonly SPEC_PURPOSE_EMPTY: 'Purpose section cannot be empty';
18
13
  readonly SPEC_NO_REQUIREMENTS: 'Spec must have at least one requirement';
19
14
  readonly CHANGE_NAME_EMPTY: 'Change name cannot be empty';
20
- readonly CHANGE_WHY_TOO_SHORT: "Why section must be at least 50 characters";
21
- readonly CHANGE_WHY_TOO_LONG: "Why section should not exceed 1000 characters";
22
15
  readonly CHANGE_WHAT_EMPTY: 'What Changes section cannot be empty';
23
16
  readonly CHANGE_NO_DELTAS: 'Change must have at least one delta';
24
17
  readonly CHANGE_TOO_MANY_DELTAS: "Consider splitting changes with more than 10 deltas";
@@ -26,10 +19,11 @@ export declare const VALIDATION_MESSAGES: {
26
19
  readonly DELTA_DESCRIPTION_EMPTY: 'Delta description cannot be empty';
27
20
  readonly PURPOSE_TOO_BRIEF: "Purpose section is too brief (less than 50 characters)";
28
21
  readonly PURPOSE_IS_PLACEHOLDER: string;
22
+ readonly DELTA_PURPOSE_TOO_BRIEF: string;
23
+ readonly DELTA_PURPOSE_MISSING: string;
24
+ readonly DELTA_PURPOSE_IS_PLACEHOLDER: string;
29
25
  readonly REQUIREMENT_TOO_LONG: "Requirement text is very long (>500 characters). Consider breaking it down.";
30
- readonly DELTA_DESCRIPTION_TOO_BRIEF: 'Delta description is too brief';
31
- readonly DELTA_MISSING_REQUIREMENTS: 'Delta should include requirements';
32
- readonly GUIDE_NO_DELTAS: 'No deltas found. Ensure your change has a specs/ directory with capability folders (e.g. specs/http-server/spec.md) containing .md files that use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each requirement includes at least one "#### Scenario:" block. Tip: run "tospec show <change-id> --json --deltas-only" to inspect parsed deltas.';
26
+ readonly GUIDE_NO_DELTAS: 'No deltas found. Ensure your change has a specs/ directory with capability folders (e.g. specs/http-server/spec.md) containing .md files that use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each requirement includes at least one "#### Scenario:" block. Tip: run "tospec show <change-id> --json" to inspect parsed deltas. If this change genuinely has no externally observable effect (tooling, CI, docs-only), set `skip_specs: true` in its .tospec.yaml instead — never invent a Requirement to satisfy this check.';
33
27
  readonly GUIDE_MISSING_SPEC_SECTIONS: 'Missing required sections. Expected headers: "## Purpose" and "## Requirements". Example:\n## Purpose\n[brief purpose]\n\n## Requirements\n### Requirement: Clear requirement statement\nUsers SHALL ...\n\n#### Scenario: Descriptive name\n- **WHEN** ...\n- **THEN** ...';
34
28
  readonly GUIDE_MISSING_CHANGE_SECTIONS: 'Missing required sections. Expected headers: "## Why" and "## What Changes". Ensure deltas are documented in specs/ using delta headers.';
35
29
  readonly GUIDE_SCENARIO_FORMAT: 'Scenarios must use level-4 headers. Convert bullet lists into:\n#### Scenario: Short name\n- **WHEN** ...\n- **THEN** ...\n- **AND** ...';
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/core/validation/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAGrC,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAQxC,eAAO,MAAM,0BAA0B,uCAAuC,CAAC;AAC/E,eAAO,MAAM,0BAA0B,oCAAoC,CAAC;AAG5E,eAAO,MAAM,mBAAmB;aAE9B,cAAc,EAAE,+BAA+B;aAC/C,iBAAiB,EAAE,kCAAkC;aACrD,oBAAoB,EAAE,gDAAgD;aACtE,wBAAwB,EAAE,6CAA6C;aACvE,eAAe,EAAE,2BAA2B;aAC5C,kBAAkB,EAAE,iCAAiC;aACrD,oBAAoB,EAAE,yCAAyC;aAC/D,iBAAiB,EAAE,6BAA6B;aAChD,oBAAoB;aACpB,mBAAmB;aACnB,iBAAiB,EAAE,sCAAsC;aACzD,gBAAgB,EAAE,qCAAqC;aACvD,sBAAsB;aACtB,gBAAgB,EAAE,2BAA2B;aAC7C,uBAAuB,EAAE,mCAAmC;aAG5D,iBAAiB;aACjB,sBAAsB;aAKtB,oBAAoB;aACpB,2BAA2B,EAAE,gCAAgC;aAC7D,0BAA0B,EAAE,mCAAmC;aAG/D,eAAe,EACb,4WAA4W;aAC9W,2BAA2B,EACzB,6QAA6Q;aAC/Q,6BAA6B,EAC3B,0IAA0I;aAC5I,qBAAqB,EACnB,0IAA0I;CACpI,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/core/validation/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAOxC,eAAO,MAAM,0BAA0B,uCAAuC,CAAC;AAC/E,eAAO,MAAM,0BAA0B,oCAAoC,CAAC;AAE5E,eAAO,MAAM,mBAAmB;aAE9B,cAAc,EAAE,+BAA+B;aAC/C,iBAAiB,EAAE,kCAAkC;aACrD,oBAAoB,EAAE,gDAAgD;aACtE,wBAAwB,EAAE,6CAA6C;aACvE,eAAe,EAAE,2BAA2B;aAC5C,kBAAkB,EAAE,iCAAiC;aACrD,oBAAoB,EAAE,yCAAyC;aAC/D,iBAAiB,EAAE,6BAA6B;aAChD,iBAAiB,EAAE,sCAAsC;aACzD,gBAAgB,EAAE,qCAAqC;aACvD,sBAAsB;aACtB,gBAAgB,EAAE,2BAA2B;aAC7C,uBAAuB,EAAE,mCAAmC;aAG5D,iBAAiB;aACjB,sBAAsB;aAQtB,uBAAuB;aAIvB,qBAAqB;aAIrB,4BAA4B;aAK5B,oBAAoB;aAKpB,eAAe,EACb,4hBAA4hB;aAC9hB,2BAA2B,EACzB,6QAA6Q;aAC/Q,6BAA6B,EAC3B,0IAA0I;aAC5I,qBAAqB,EACnB,0IAA0I;CACpI,CAAC"}
@@ -1,22 +1,16 @@
1
- /**
2
- * Validation threshold constants
3
- */
4
- // Minimum character lengths
5
- export const MIN_WHY_SECTION_LENGTH = 50;
1
+ // Thresholds shared by the validator's imperative checks. Per-section bounds
2
+ // such as `Why`'s are not here: those are declared per artifact in
3
+ // `schemas/<name>/schema.yaml` (`minSectionLength` / `maxSectionLength`).
6
4
  export const MIN_PURPOSE_LENGTH = 50;
7
- // Maximum character/item limits
8
- export const MAX_WHY_SECTION_LENGTH = 1000;
9
5
  export const MAX_REQUIREMENT_TEXT_LENGTH = 500;
10
6
  export const MAX_DELTAS_PER_CHANGE = 10;
11
- // The Purpose `tospec archive` stamps into a main spec it creates when the delta
12
- // introduced the capability without a usable `## Purpose`. Named here and
13
- // composed from these two halves at the write site so validation recognises the
14
- // placeholder through the same definition that produces it: a second, hand-copied
15
- // spelling stops matching the day the wording changes, and a check that matches
16
- // nothing looks exactly like a check that found nothing.
7
+ // The Purpose `tospec archive` stamps into a main spec it creates for a delta
8
+ // that introduced the capability without a usable `## Purpose`. Composed from
9
+ // these two halves at the write site so validation recognises it through the
10
+ // same definition that produces it: a second spelling stops matching the day
11
+ // the wording changes, and a check that matches nothing looks like a clean one.
17
12
  export const PURPOSE_PLACEHOLDER_PREFIX = 'TBD - created by archiving change ';
18
13
  export const PURPOSE_PLACEHOLDER_SUFFIX = '. Update Purpose after archive.';
19
- // Validation messages
20
14
  export const VALIDATION_MESSAGES = {
21
15
  // Required content
22
16
  SCENARIO_EMPTY: 'Scenario text cannot be empty',
@@ -27,8 +21,6 @@ export const VALIDATION_MESSAGES = {
27
21
  SPEC_PURPOSE_EMPTY: 'Purpose section cannot be empty',
28
22
  SPEC_NO_REQUIREMENTS: 'Spec must have at least one requirement',
29
23
  CHANGE_NAME_EMPTY: 'Change name cannot be empty',
30
- CHANGE_WHY_TOO_SHORT: `Why section must be at least ${MIN_WHY_SECTION_LENGTH} characters`,
31
- CHANGE_WHY_TOO_LONG: `Why section should not exceed ${MAX_WHY_SECTION_LENGTH} characters`,
32
24
  CHANGE_WHAT_EMPTY: 'What Changes section cannot be empty',
33
25
  CHANGE_NO_DELTAS: 'Change must have at least one delta',
34
26
  CHANGE_TOO_MANY_DELTAS: `Consider splitting changes with more than ${MAX_DELTAS_PER_CHANGE} deltas`,
@@ -40,11 +32,24 @@ export const VALIDATION_MESSAGES = {
40
32
  'writes for a new capability, or a `TBD`/`TODO` marker left in its place). Replace it with what this ' +
41
33
  'capability is for, editing the main spec directly: a `## Purpose` in a delta is read only when the ' +
42
34
  'capability is created, so it cannot replace this one.',
35
+ // Delta-side twins of the two rules above, worded separately on purpose: the
36
+ // main-spec messages say to edit the main spec, and there is none to edit
37
+ // while the capability exists only as a delta.
38
+ DELTA_PURPOSE_TOO_BRIEF: `Purpose section is too brief (less than ${MIN_PURPOSE_LENGTH} characters). ` +
39
+ 'This capability has no main spec yet, so `tospec archive` will copy this Purpose into the one it ' +
40
+ 'creates — write it here, in the delta, while you still can.',
41
+ DELTA_PURPOSE_MISSING: 'Delta has no `## Purpose`. This capability has no main spec yet, so `tospec archive` will create ' +
42
+ 'one and, with nothing to copy, write a `TBD` placeholder as its Purpose. Open the delta with one ' +
43
+ 'sentence on why this capability exists.',
44
+ DELTA_PURPOSE_IS_PLACEHOLDER: 'Purpose section is still a placeholder rather than a Purpose anyone wrote (a `TBD`/`TODO` marker, or ' +
45
+ 'the sentence `tospec archive` writes when a delta supplies none). This capability has no main spec ' +
46
+ 'yet, so archive will copy this text into the one it creates — replace it here, in the delta, with ' +
47
+ 'what this capability is for.',
43
48
  REQUIREMENT_TOO_LONG: `Requirement text is very long (>${MAX_REQUIREMENT_TEXT_LENGTH} characters). Consider breaking it down.`,
44
- DELTA_DESCRIPTION_TOO_BRIEF: 'Delta description is too brief',
45
- DELTA_MISSING_REQUIREMENTS: 'Delta should include requirements',
46
- // Guidance snippets (appended to primary messages for remediation)
47
- GUIDE_NO_DELTAS: 'No deltas found. Ensure your change has a specs/ directory with capability folders (e.g. specs/http-server/spec.md) containing .md files that use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each requirement includes at least one "#### Scenario:" block. Tip: run "tospec show <change-id> --json --deltas-only" to inspect parsed deltas.',
49
+ // Guidance snippets, appended to a primary message. The skip_specs sentence is
50
+ // load-bearing: without it the only way out offered is "write a delta", to a
51
+ // change that may genuinely have no observable behaviour.
52
+ GUIDE_NO_DELTAS: 'No deltas found. Ensure your change has a specs/ directory with capability folders (e.g. specs/http-server/spec.md) containing .md files that use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each requirement includes at least one "#### Scenario:" block. Tip: run "tospec show <change-id> --json" to inspect parsed deltas. If this change genuinely has no externally observable effect (tooling, CI, docs-only), set `skip_specs: true` in its .tospec.yaml instead — never invent a Requirement to satisfy this check.',
48
53
  GUIDE_MISSING_SPEC_SECTIONS: 'Missing required sections. Expected headers: "## Purpose" and "## Requirements". Example:\n## Purpose\n[brief purpose]\n\n## Requirements\n### Requirement: Clear requirement statement\nUsers SHALL ...\n\n#### Scenario: Descriptive name\n- **WHEN** ...\n- **THEN** ...',
49
54
  GUIDE_MISSING_CHANGE_SECTIONS: 'Missing required sections. Expected headers: "## Why" and "## What Changes". Ensure deltas are documented in specs/ using delta headers.',
50
55
  GUIDE_SCENARIO_FORMAT: 'Scenarios must use level-4 headers. Convert bullet lists into:\n#### Scenario: Short name\n- **WHEN** ...\n- **THEN** ...\n- **AND** ...',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/core/validation/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,4BAA4B;AAC5B,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,gCAAgC;AAChC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAExC,iFAAiF;AACjF,0EAA0E;AAC1E,gFAAgF;AAChF,kFAAkF;AAClF,gFAAgF;AAChF,yDAAyD;AACzD,MAAM,CAAC,MAAM,0BAA0B,GAAG,oCAAoC,CAAC;AAC/E,MAAM,CAAC,MAAM,0BAA0B,GAAG,iCAAiC,CAAC;AAE5E,sBAAsB;AACtB,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,mBAAmB;IACnB,cAAc,EAAE,+BAA+B;IAC/C,iBAAiB,EAAE,kCAAkC;IACrD,oBAAoB,EAAE,gDAAgD;IACtE,wBAAwB,EAAE,6CAA6C;IACvE,eAAe,EAAE,2BAA2B;IAC5C,kBAAkB,EAAE,iCAAiC;IACrD,oBAAoB,EAAE,yCAAyC;IAC/D,iBAAiB,EAAE,6BAA6B;IAChD,oBAAoB,EAAE,gCAAgC,sBAAsB,aAAa;IACzF,mBAAmB,EAAE,iCAAiC,sBAAsB,aAAa;IACzF,iBAAiB,EAAE,sCAAsC;IACzD,gBAAgB,EAAE,qCAAqC;IACvD,sBAAsB,EAAE,6CAA6C,qBAAqB,SAAS;IACnG,gBAAgB,EAAE,2BAA2B;IAC7C,uBAAuB,EAAE,mCAAmC;IAE5D,WAAW;IACX,iBAAiB,EAAE,2CAA2C,kBAAkB,cAAc;IAC9F,sBAAsB,EACpB,2GAA2G;QAC3G,sGAAsG;QACtG,qGAAqG;QACrG,uDAAuD;IACzD,oBAAoB,EAAE,mCAAmC,2BAA2B,0CAA0C;IAC9H,2BAA2B,EAAE,gCAAgC;IAC7D,0BAA0B,EAAE,mCAAmC;IAE/D,mEAAmE;IACnE,eAAe,EACb,4WAA4W;IAC9W,2BAA2B,EACzB,6QAA6Q;IAC/Q,6BAA6B,EAC3B,0IAA0I;IAC5I,qBAAqB,EACnB,0IAA0I;CACpI,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/core/validation/constants.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,mEAAmE;AACnE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAExC,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,oCAAoC,CAAC;AAC/E,MAAM,CAAC,MAAM,0BAA0B,GAAG,iCAAiC,CAAC;AAE5E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,mBAAmB;IACnB,cAAc,EAAE,+BAA+B;IAC/C,iBAAiB,EAAE,kCAAkC;IACrD,oBAAoB,EAAE,gDAAgD;IACtE,wBAAwB,EAAE,6CAA6C;IACvE,eAAe,EAAE,2BAA2B;IAC5C,kBAAkB,EAAE,iCAAiC;IACrD,oBAAoB,EAAE,yCAAyC;IAC/D,iBAAiB,EAAE,6BAA6B;IAChD,iBAAiB,EAAE,sCAAsC;IACzD,gBAAgB,EAAE,qCAAqC;IACvD,sBAAsB,EAAE,6CAA6C,qBAAqB,SAAS;IACnG,gBAAgB,EAAE,2BAA2B;IAC7C,uBAAuB,EAAE,mCAAmC;IAE5D,WAAW;IACX,iBAAiB,EAAE,2CAA2C,kBAAkB,cAAc;IAC9F,sBAAsB,EACpB,2GAA2G;QAC3G,sGAAsG;QACtG,qGAAqG;QACrG,uDAAuD;IACzD,6EAA6E;IAC7E,0EAA0E;IAC1E,+CAA+C;IAC/C,uBAAuB,EACrB,2CAA2C,kBAAkB,gBAAgB;QAC7E,mGAAmG;QACnG,6DAA6D;IAC/D,qBAAqB,EACnB,mGAAmG;QACnG,mGAAmG;QACnG,yCAAyC;IAC3C,4BAA4B,EAC1B,uGAAuG;QACvG,qGAAqG;QACrG,oGAAoG;QACpG,8BAA8B;IAChC,oBAAoB,EAAE,mCAAmC,2BAA2B,0CAA0C;IAE9H,+EAA+E;IAC/E,6EAA6E;IAC7E,0DAA0D;IAC1D,eAAe,EACb,4hBAA4hB;IAC9hB,2BAA2B,EACzB,6QAA6Q;IAC/Q,6BAA6B,EAC3B,0IAA0I;IAC5I,qBAAqB,EACnB,0IAA0I;CACpI,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * How much prose a string carries, one unit being roughly one English
3
+ * character.
4
+ *
5
+ * The minimum-length thresholds were calibrated on English — 50 characters is
6
+ * about eight words — while the same eight words of Traditional Chinese are
7
+ * around 20, so a full answer reads as too brief purely for being written in
8
+ * Chinese. Counting a double-width character as two units puts both languages
9
+ * on one scale.
10
+ *
11
+ * Applied to minimums only. A maximum asks "is this an essay?", where the raw
12
+ * character count is the conservative answer.
13
+ */
14
+ export declare function proseLength(text: string): number;
15
+ //# sourceMappingURL=prose-length.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose-length.d.ts","sourceRoot":"","sources":["../../../src/core/validation/prose-length.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * East Asian Wide and Fullwidth code points — the ones a terminal draws in two
3
+ * columns. The conventional wcwidth set, not a full Unicode property scan: this
4
+ * is a length *heuristic*, and a missed rare block costs one unit.
5
+ */
6
+ const WIDE_CHARACTER = /[ᄀ-ᅟ⺀-〾ぁ-㏿㐀-䶿一-鿿ꀀ-꓏가-힣豈-﫿︐-︙︰-﹯＀-⦆¢-₩]|[\u{20000}-\u{3FFFD}]/u;
7
+ /**
8
+ * How much prose a string carries, one unit being roughly one English
9
+ * character.
10
+ *
11
+ * The minimum-length thresholds were calibrated on English — 50 characters is
12
+ * about eight words — while the same eight words of Traditional Chinese are
13
+ * around 20, so a full answer reads as too brief purely for being written in
14
+ * Chinese. Counting a double-width character as two units puts both languages
15
+ * on one scale.
16
+ *
17
+ * Applied to minimums only. A maximum asks "is this an essay?", where the raw
18
+ * character count is the conservative answer.
19
+ */
20
+ export function proseLength(text) {
21
+ let units = 0;
22
+ // Iterating yields whole code points, so an astral CJK character counts once
23
+ // (as 2 units) rather than twice as its surrogate halves.
24
+ for (const character of text) {
25
+ units += WIDE_CHARACTER.test(character) ? 2 : 1;
26
+ }
27
+ return units;
28
+ }
29
+ //# sourceMappingURL=prose-length.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose-length.js","sourceRoot":"","sources":["../../../src/core/validation/prose-length.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,cAAc,GAClB,+DAA+D,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,6EAA6E;IAC7E,0DAA0D;IAC1D,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -2,24 +2,17 @@
2
2
  * Detects a `## Purpose` that is still a placeholder rather than one somebody
3
3
  * wrote.
4
4
  *
5
- * When a delta introduces a capability with no usable `## Purpose`, archive
6
- * stamps the placeholder into the new main spec. That text is longer than
7
- * MIN_PURPOSE_LENGTH, so the brevity check cannot reach it: the one rule that
8
- * exists to catch a Purpose nobody wrote is satisfied by the exact string
9
- * meaning nobody wrote one. Nothing else read it afterwards, so the capability
10
- * kept a to-do in it while every command reported success.
5
+ * Archive's generated placeholder is longer than MIN_PURPOSE_LENGTH, so the
6
+ * brevity check cannot reach it.
11
7
  *
12
8
  * Two things count, and deliberately nothing else:
13
9
  *
14
- * - the placeholder this tool generates, recognised through the same constants
15
- * the writer composes it from, wherever it sits in the Purpose — nobody types
16
- * that sentence by accident;
17
- * - a `TBD` or `TODO` *opening* the Purpose, which is the marker left behind
18
- * when someone is told to leave a brief placeholder and never comes back.
10
+ * - the generated placeholder, recognised through the same constants the writer
11
+ * composes it from, wherever it sits;
12
+ * - a `TBD` or `TODO` *opening* the Purpose.
19
13
  *
20
14
  * A marker inside a sentence is left alone: "the retry budget is TBD pending
21
- * benchmarks" is a real Purpose with an open question in it, and reporting it
22
- * would teach people to ignore the warning.
15
+ * benchmarks" is a real Purpose with an open question in it.
23
16
  */
24
17
  export interface PurposePlaceholderIssue {
25
18
  /** 1-based line of the placeholder text, when it can be located. */
@@ -29,9 +22,9 @@ export interface PurposePlaceholderIssue {
29
22
  * Reports the Purpose of a main spec as an unwritten placeholder, or null when
30
23
  * it reads as authored content.
31
24
  *
32
- * An empty Purpose needs no branch of its own: neither rule matches empty text,
33
- * so it falls through to null and SPEC_PURPOSE_EMPTY covers it alone. A Purpose
34
- * that is nothing but a fenced block reduces to the same empty text here.
25
+ * An empty Purpose needs no branch: neither rule matches empty text, so it falls
26
+ * through to null and SPEC_PURPOSE_EMPTY covers it. A Purpose that is nothing
27
+ * but a fenced block reduces to the same empty text here.
35
28
  */
36
29
  export declare function findPurposePlaceholderIssue(overview: string, content?: string): PurposePlaceholderIssue | null;
37
30
  //# sourceMappingURL=purpose-placeholder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"purpose-placeholder.d.ts","sourceRoot":"","sources":["../../../src/core/validation/purpose-placeholder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA+CD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,uBAAuB,GAAG,IAAI,CAOhC"}
1
+ {"version":3,"file":"purpose-placeholder.d.ts","sourceRoot":"","sources":["../../../src/core/validation/purpose-placeholder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2CD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,uBAAuB,GAAG,IAAI,CAOhC"}
@@ -2,62 +2,51 @@
2
2
  * Detects a `## Purpose` that is still a placeholder rather than one somebody
3
3
  * wrote.
4
4
  *
5
- * When a delta introduces a capability with no usable `## Purpose`, archive
6
- * stamps the placeholder into the new main spec. That text is longer than
7
- * MIN_PURPOSE_LENGTH, so the brevity check cannot reach it: the one rule that
8
- * exists to catch a Purpose nobody wrote is satisfied by the exact string
9
- * meaning nobody wrote one. Nothing else read it afterwards, so the capability
10
- * kept a to-do in it while every command reported success.
5
+ * Archive's generated placeholder is longer than MIN_PURPOSE_LENGTH, so the
6
+ * brevity check cannot reach it.
11
7
  *
12
8
  * Two things count, and deliberately nothing else:
13
9
  *
14
- * - the placeholder this tool generates, recognised through the same constants
15
- * the writer composes it from, wherever it sits in the Purpose — nobody types
16
- * that sentence by accident;
17
- * - a `TBD` or `TODO` *opening* the Purpose, which is the marker left behind
18
- * when someone is told to leave a brief placeholder and never comes back.
10
+ * - the generated placeholder, recognised through the same constants the writer
11
+ * composes it from, wherever it sits;
12
+ * - a `TBD` or `TODO` *opening* the Purpose.
19
13
  *
20
14
  * A marker inside a sentence is left alone: "the retry budget is TBD pending
21
- * benchmarks" is a real Purpose with an open question in it, and reporting it
22
- * would teach people to ignore the warning.
15
+ * benchmarks" is a real Purpose with an open question in it.
23
16
  */
24
- import { buildCodeFenceMask } from '../parsers/requirement-text.js';
17
+ import { buildCodeFenceMask, normalizeDocument } from '../parsers/requirement-text.js';
25
18
  import { PURPOSE_PLACEHOLDER_PREFIX, PURPOSE_PLACEHOLDER_SUFFIX } from './constants.js';
26
19
  /**
27
20
  * A `TBD`/`TODO` opening the Purpose. The lookahead keeps it off a longer word
28
- * that merely starts with those letters ("TODOs are tracked in the issue") while
29
- * still allowing the punctuation a marker is written with: `TODO:`, `TBD -`. It
30
- * rejects any letter, digit or combining mark rather than only the ASCII ones
31
- * `\b` knows about — a Purpose is prose and prose is not always Latin script.
21
+ * starting with those letters ("TODOs are tracked in the issue") while allowing
22
+ * the punctuation a marker carries: `TODO:`, `TBD -`. It rejects any letter,
23
+ * digit or combining mark rather than only the ASCII ones `\b` knows about,
24
+ * since a Purpose is prose and prose is not always Latin script.
32
25
  */
33
26
  const LEADING_MARKER = /^(?:TBD|TODO)(?![\p{L}\p{N}\p{M}_])/iu;
34
27
  const PURPOSE_HEADER = /^ {0,3}##(?!#)[ \t]+Purpose[ \t]*$/i;
35
28
  const TOP_LEVEL_HEADER = /^ {0,3}#{1,2}(?!#)[ \t]+/;
36
29
  /**
37
- * The lines of `text` outside a fenced code block, line endings normalised.
38
- *
39
- * Fenced content is quoted material, not the Purpose speaking. Without this a
40
- * spec documenting the sentence archive writes is reported as carrying it — the
41
- * check failing the one document that explains it. `buildCodeFenceMask` is the
42
- * masker the requirement and structure parsers already share, so all three read
43
- * fences the same way.
30
+ * The lines of `text` outside a fenced code block. Fenced content is quoted
31
+ * material, not the Purpose speaking: without this, a spec documenting the
32
+ * sentence archive writes is reported as carrying it.
44
33
  */
45
34
  function unfencedLines(text) {
46
- const lines = text.replace(/\r\n?/g, '\n').split('\n');
35
+ const lines = normalizeDocument(text).split('\n');
47
36
  const fenced = buildCodeFenceMask(lines);
48
37
  return lines.filter((_, index) => !fenced[index]);
49
38
  }
50
39
  /**
51
40
  * Offset of the generated placeholder in `text`, or undefined. Matched as its
52
- * two fixed halves in order because the change name between them varies — the
53
- * check follows the writer's own definition instead of a second copy of it.
41
+ * two fixed halves in order because the change name between them varies, so the
42
+ * check follows the writer's own definition rather than a copy of it.
54
43
  */
55
44
  function generatedPlaceholderPrefixIndex(text) {
56
45
  let suffixAt = text.indexOf(PURPOSE_PLACEHOLDER_SUFFIX);
57
46
  while (suffixAt !== -1) {
58
47
  // The closest prefix before this suffix: authored prose can mention the
59
- // prefix above the real placeholder, and the first prefix would then point
60
- // the diagnostic at the explanation instead of the text to replace.
48
+ // prefix above the real placeholder, and the first one would point the
49
+ // diagnostic at the explanation instead of the text to replace.
61
50
  const prefixAt = text.lastIndexOf(PURPOSE_PLACEHOLDER_PREFIX, suffixAt);
62
51
  if (prefixAt !== -1)
63
52
  return prefixAt;
@@ -69,9 +58,9 @@ function generatedPlaceholderPrefixIndex(text) {
69
58
  * Reports the Purpose of a main spec as an unwritten placeholder, or null when
70
59
  * it reads as authored content.
71
60
  *
72
- * An empty Purpose needs no branch of its own: neither rule matches empty text,
73
- * so it falls through to null and SPEC_PURPOSE_EMPTY covers it alone. A Purpose
74
- * that is nothing but a fenced block reduces to the same empty text here.
61
+ * An empty Purpose needs no branch: neither rule matches empty text, so it falls
62
+ * through to null and SPEC_PURPOSE_EMPTY covers it. A Purpose that is nothing
63
+ * but a fenced block reduces to the same empty text here.
75
64
  */
76
65
  export function findPurposePlaceholderIssue(overview, content) {
77
66
  const prose = unfencedLines(overview).join('\n').trim();
@@ -79,7 +68,7 @@ export function findPurposePlaceholderIssue(overview, content) {
79
68
  if (!leading && generatedPlaceholderPrefixIndex(prose) === undefined)
80
69
  return null;
81
70
  // Which rule matched decides where the placeholder sits, so the locator is
82
- // told. When both match the leading marker wins — it is the earlier of the two.
71
+ // told. When both match the leading marker wins, being the earlier.
83
72
  return { line: content === undefined ? undefined : findPlaceholderLine(content, leading) };
84
73
  }
85
74
  /**
@@ -87,25 +76,22 @@ export function findPurposePlaceholderIssue(overview, content) {
87
76
  * at the text to replace rather than at the file.
88
77
  *
89
78
  * Which line that is depends on the rule that matched. A leading marker is the
90
- * section's first non-blank line by definition; the generated sentence is not —
91
- * it can follow prose somebody wrote, and naming the first non-blank line then
92
- * points at a line the reader can see is fine, which reads as the check being
93
- * broken rather than the Purpose being unwritten.
79
+ * section's first non-blank line by definition; the generated sentence is not,
80
+ * and can follow prose somebody wrote.
94
81
  *
95
- * Undefined when the placeholder cannot be located, because a wrong line number
96
- * is worse than none. Line endings are normalised first so the same spec reports
97
- * the same line on Windows and on macOS/Linux.
82
+ * Undefined when the placeholder cannot be located: a wrong line number is worse
83
+ * than none.
98
84
  */
99
85
  function findPlaceholderLine(content, leading) {
100
- const lines = content.replace(/\r\n?/g, '\n').split('\n');
86
+ const lines = normalizeDocument(content).split('\n');
101
87
  const fenced = buildCodeFenceMask(lines);
102
88
  const headerIndex = lines.findIndex((line, index) => !fenced[index] && PURPOSE_HEADER.test(line));
103
89
  if (headerIndex === -1)
104
90
  return undefined;
105
91
  const purposeLines = [];
106
92
  for (let i = headerIndex + 1; i < lines.length; i++) {
107
- // Fenced lines are skipped for the reason detection skips them, and so a
108
- // `## Requirements` quoted inside a fence cannot end the section early.
93
+ // Skipped as in detection, and so a `## Requirements` quoted inside a fence
94
+ // cannot end the section early.
109
95
  if (fenced[i])
110
96
  continue;
111
97
  if (TOP_LEVEL_HEADER.test(lines[i]))
@@ -1 +1 @@
1
- {"version":3,"file":"purpose-placeholder.js","sourceRoot":"","sources":["../../../src/core/validation/purpose-placeholder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"purpose-placeholder.js","sourceRoot":"","sources":["../../../src/core/validation/purpose-placeholder.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { ValidationIssue } from './types.js';
2
2
  export interface SectionValidationRules {
3
3
  requiredSections: string[];
4
4
  minSectionLength: Record<string, number>;
5
+ maxSectionLength?: Record<string, number>;
5
6
  }
6
7
  export interface SectionValidationContext {
7
8
  /** Reported as ValidationIssue.path (typically the file's relative path). */
@@ -10,10 +11,9 @@ export interface SectionValidationContext {
10
11
  templateRef?: string;
11
12
  }
12
13
  /**
13
- * Validates a document's headings against schema-declared rules, for
14
- * artifacts (ticket.md, design.md, task.md, ...) that have no Requirement
15
- * grammar to check structurally. Rules live in schema.yaml so new document
16
- * types don't require validator code changes.
14
+ * Heading rules for artifacts (ticket.md, design.md, task.md, ...) that have no
15
+ * Requirement grammar to check structurally. The rules live in schema.yaml so a
16
+ * new document type needs no validator code.
17
17
  */
18
18
  export declare function validateSections(content: string, rules: SectionValidationRules, context: SectionValidationContext): ValidationIssue[];
19
19
  //# sourceMappingURL=section-validator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"section-validator.d.ts","sourceRoot":"","sources":["../../../src/core/validation/section-validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,sBAAsB,EAC7B,OAAO,EAAE,wBAAwB,GAChC,eAAe,EAAE,CAwCnB"}
1
+ {"version":3,"file":"section-validator.d.ts","sourceRoot":"","sources":["../../../src/core/validation/section-validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAcD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,sBAAsB,EAC7B,OAAO,EAAE,wBAAwB,GAChC,eAAe,EAAE,CAiEnB"}
@@ -1,9 +1,20 @@
1
1
  import { MarkdownParser, findSection } from '../parsers/markdown-parser.js';
2
+ import { proseLength } from './prose-length.js';
2
3
  /**
3
- * Validates a document's headings against schema-declared rules, for
4
- * artifacts (ticket.md, design.md, task.md, ...) that have no Requirement
5
- * grammar to check structurally. Rules live in schema.yaml so new document
6
- * types don't require validator code changes.
4
+ * The prose a section actually carries, with HTML comments removed.
5
+ *
6
+ * Templates put their guidance in `<!-- ... -->`, which counts as text to a
7
+ * naive length check: the proposal template's Why hint is 71 characters against
8
+ * a 50-character minimum, so an untouched template would satisfy its own
9
+ * threshold while a real ten-word answer is warned about.
10
+ */
11
+ function authoredContent(sectionContent) {
12
+ return sectionContent.replace(/<!--[\s\S]*?-->/g, '').trim();
13
+ }
14
+ /**
15
+ * Heading rules for artifacts (ticket.md, design.md, task.md, ...) that have no
16
+ * Requirement grammar to check structurally. The rules live in schema.yaml so a
17
+ * new document type needs no validator code.
7
18
  */
8
19
  export function validateSections(content, rules, context) {
9
20
  const issues = [];
@@ -19,11 +30,17 @@ export function validateSections(content, rules, context) {
19
30
  });
20
31
  continue;
21
32
  }
22
- if (!section.content.trim()) {
33
+ if (!authoredContent(section.content)) {
34
+ // Told apart because the fix differs: a blank section needs writing, a
35
+ // comment-only one needs the placeholder replaced — and "is empty" reads
36
+ // as wrong to someone looking at text under the heading.
37
+ const onlyComments = section.content.trim().length > 0;
23
38
  issues.push({
24
39
  level: 'WARNING',
25
40
  path: context.path,
26
- message: `Section "${requiredTitle}" is empty`,
41
+ message: onlyComments
42
+ ? `Section "${requiredTitle}" still holds only the template's guidance comment`
43
+ : `Section "${requiredTitle}" is empty`,
27
44
  });
28
45
  }
29
46
  }
@@ -32,7 +49,9 @@ export function validateSections(content, rules, context) {
32
49
  if (!section) {
33
50
  continue; // absence is already reported above when also required
34
51
  }
35
- const length = section.content.trim().length;
52
+ // Width-aware, so the English-calibrated threshold means the same amount
53
+ // of prose in a double-width script.
54
+ const length = proseLength(authoredContent(section.content));
36
55
  if (length > 0 && length < minLength) {
37
56
  issues.push({
38
57
  level: 'WARNING',
@@ -41,6 +60,23 @@ export function validateSections(content, rules, context) {
41
60
  });
42
61
  }
43
62
  }
63
+ for (const [sectionTitle, maxLength] of Object.entries(rules.maxSectionLength ?? {})) {
64
+ const section = findSection(sections, sectionTitle);
65
+ if (!section)
66
+ continue;
67
+ // Raw characters: unlike the floor, a ceiling asks "is this an essay?", and
68
+ // widening the unit for double-width scripts would reject long but
69
+ // legitimate CJK prose.
70
+ // tospec/decisions/20260919_193441-width-aware-minimum-length.md
71
+ const length = authoredContent(section.content).length;
72
+ if (length > maxLength) {
73
+ issues.push({
74
+ level: 'WARNING',
75
+ path: context.path,
76
+ message: `Section "${sectionTitle}" is longer than the recommended ${maxLength} characters (found ${length}) — consider moving detail into design.md or splitting the change`,
77
+ });
78
+ }
79
+ }
44
80
  return issues;
45
81
  }
46
82
  //# sourceMappingURL=section-validator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"section-validator.js","sourceRoot":"","sources":["../../../src/core/validation/section-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAe5E;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,KAA6B,EAC7B,OAAiC;IAEjC,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAE3D,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,mBAAmB,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,6BAA6B,aAAa,IAAI,IAAI,EAAE;aAC9D,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,YAAY,aAAa,YAAY;aAC/C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/E,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,SAAS,CAAC,uDAAuD;QACnE,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;QAC7C,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,YAAY,YAAY,qCAAqC,SAAS,sBAAsB,MAAM,GAAG;aAC/G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"section-validator.js","sourceRoot":"","sources":["../../../src/core/validation/section-validator.ts"],"names":[],"mappings":"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"}
@@ -3,11 +3,14 @@
3
3
  *
4
4
  * Task IDs are how apply refers to work ("continue with 2.3"), so a duplicated
5
5
  * ID or one that contradicts its group heading makes that reference point at
6
- * the wrong item — silently, because nothing else reads the numbers.
6
+ * the wrong item, silently.
7
7
  *
8
8
  * Numbering is interpreted only inside numbered group headings. Unnumbered
9
- * sections, unnumbered tasks, and files with no numbered group at all are
10
- * ignored on purpose: they are a legitimate style, not a defect.
9
+ * sections and tasks are a legitimate style, not a defect.
10
+ *
11
+ * Gaps are not checked: 1.1 followed by 1.3 still leaves every ID pointing at
12
+ * exactly one task, which is the property this module defends. Demanding a
13
+ * renumber would invalidate every reference already made.
11
14
  */
12
15
  export interface TaskNumberingDocument {
13
16
  /** Display path, relative to the change directory. */
@@ -1 +1 @@
1
- {"version":3,"file":"task-numbering.d.ts","sourceRoot":"","sources":["../../../src/core/validation/task-numbering.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAsBD,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,qBAAqB,EAAE,GAC1C,kBAAkB,EAAE,CAuDtB"}
1
+ {"version":3,"file":"task-numbering.d.ts","sourceRoot":"","sources":["../../../src/core/validation/task-numbering.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAsBD,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,qBAAqB,EAAE,GAC1C,kBAAkB,EAAE,CAkEtB"}
@@ -1,9 +1,10 @@
1
1
  import { parseTasksFromContent } from '../../utils/task-progress.js';
2
+ import { buildCodeFenceMask, normalizeDocument } from '../parsers/requirement-text.js';
2
3
  /**
3
4
  * A group heading is level 2 or 3, because the two schemas differ: sdd's
4
- * `tasks.md` numbers slices at `## 1.`, while issue's `task.md` puts `### 1. Fix`
5
- * under an unnumbered `## Tasks`. Matching only one level would make the check
6
- * silently inert for the other schema.
5
+ * `tasks.md` numbers slices at `## 1.`, while issue's `task.md` puts
6
+ * `### 1. Fix` under an unnumbered `## Tasks`. Matching one level would leave
7
+ * the check inert for the other schema.
7
8
  */
8
9
  const GROUP_HEADING = /^ {0,3}#{2,3}[ \t]+/;
9
10
  const NUMBERED_GROUP_HEADING = /^ {0,3}#{2,3}[ \t]+(\d+)\./;
@@ -15,24 +16,35 @@ export function findTaskNumberingIssues(documents) {
15
16
  const issues = [];
16
17
  const firstLocationById = new Map();
17
18
  for (const document of documents) {
18
- const lines = document.content.split(/\r?\n/);
19
+ const lines = normalizeDocument(document.content).split('\n');
19
20
  if (!lines.some((line) => NUMBERED_GROUP_HEADING.test(line)))
20
21
  continue;
22
+ // Parsed once for the whole document, then addressed by line — never
23
+ // `parseTasksFromContent(line)` per line, which opts out of fence masking:
24
+ // the mask is built from surrounding lines, so a line handed over alone can
25
+ // never be inside a fence, and a tasks.md documenting its own format would
26
+ // draw warnings over its fenced examples.
27
+ const taskByLine = new Map();
28
+ for (const task of parseTasksFromContent(document.content)) {
29
+ taskByLine.set(task.line, task);
30
+ }
31
+ // Headings need the mask for the same reason: a `## 9. …` inside a fence is
32
+ // a quoted example, and letting it open a numbered group misjudges every
33
+ // real task below it.
34
+ const fenced = buildCodeFenceMask(lines);
21
35
  let currentGroup;
22
36
  lines.forEach((line, index) => {
37
+ if (fenced[index])
38
+ return;
23
39
  if (GROUP_HEADING.test(line)) {
24
- // An unnumbered heading at either level ends the numbered group rather
25
- // than letting it leak across sections.
40
+ // An unnumbered heading at either level ends the numbered group, so it
41
+ // cannot leak across sections.
26
42
  currentGroup = line.match(NUMBERED_GROUP_HEADING)?.[1];
27
43
  return;
28
44
  }
29
45
  if (currentGroup === undefined)
30
46
  return;
31
- // Deliberately the same line-based reader progress counting uses, fenced
32
- // blocks and all. A checkbox in a fence is miscounted by both or neither;
33
- // making only this side fence-aware would put the two readers back out of
34
- // step, which is the failure mode worth avoiding here.
35
- const task = parseTasksFromContent(line)[0];
47
+ const task = taskByLine.get(index + 1);
36
48
  const id = task?.text.match(TASK_ID)?.[1];
37
49
  if (!id)
38
50
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"task-numbering.js","sourceRoot":"","sources":["../../../src/core/validation/task-numbering.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-numbering.js","sourceRoot":"","sources":["../../../src/core/validation/task-numbering.ts"],"names":[],"mappings":"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"}