@seanmars/tospec 0.24.0 → 0.26.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 (332) hide show
  1. package/CHANGELOG.md +243 -0
  2. package/README.md +10 -6
  3. package/assets/dashboard/lib/derive.js +11 -5
  4. package/assets/dashboard/lib/store.js +4 -2
  5. package/assets/dashboard/views/change.js +5 -3
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +42 -7
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/commands/config.d.ts.map +1 -1
  10. package/dist/commands/config.js +213 -100
  11. package/dist/commands/config.js.map +1 -1
  12. package/dist/commands/dashboard.d.ts +9 -0
  13. package/dist/commands/dashboard.d.ts.map +1 -1
  14. package/dist/commands/dashboard.js +77 -21
  15. package/dist/commands/dashboard.js.map +1 -1
  16. package/dist/commands/decision.d.ts +38 -1
  17. package/dist/commands/decision.d.ts.map +1 -1
  18. package/dist/commands/decision.js +303 -27
  19. package/dist/commands/decision.js.map +1 -1
  20. package/dist/commands/metrics.d.ts +3 -4
  21. package/dist/commands/metrics.d.ts.map +1 -1
  22. package/dist/commands/metrics.js +3 -5
  23. package/dist/commands/metrics.js.map +1 -1
  24. package/dist/commands/shared-output.d.ts +24 -0
  25. package/dist/commands/shared-output.d.ts.map +1 -1
  26. package/dist/commands/shared-output.js +21 -2
  27. package/dist/commands/shared-output.js.map +1 -1
  28. package/dist/commands/show.d.ts.map +1 -1
  29. package/dist/commands/show.js +12 -9
  30. package/dist/commands/show.js.map +1 -1
  31. package/dist/commands/validate.d.ts +19 -0
  32. package/dist/commands/validate.d.ts.map +1 -1
  33. package/dist/commands/validate.js +243 -64
  34. package/dist/commands/validate.js.map +1 -1
  35. package/dist/commands/workflow/instructions.d.ts +7 -1
  36. package/dist/commands/workflow/instructions.d.ts.map +1 -1
  37. package/dist/commands/workflow/instructions.js +299 -81
  38. package/dist/commands/workflow/instructions.js.map +1 -1
  39. package/dist/commands/workflow/new-change.d.ts.map +1 -1
  40. package/dist/commands/workflow/new-change.js +26 -17
  41. package/dist/commands/workflow/new-change.js.map +1 -1
  42. package/dist/commands/workflow/prompt-escape.d.ts +25 -0
  43. package/dist/commands/workflow/prompt-escape.d.ts.map +1 -0
  44. package/dist/commands/workflow/prompt-escape.js +62 -0
  45. package/dist/commands/workflow/prompt-escape.js.map +1 -0
  46. package/dist/commands/workflow/schemas.d.ts.map +1 -1
  47. package/dist/commands/workflow/schemas.js +34 -16
  48. package/dist/commands/workflow/schemas.js.map +1 -1
  49. package/dist/commands/workflow/shared.d.ts +46 -10
  50. package/dist/commands/workflow/shared.d.ts.map +1 -1
  51. package/dist/commands/workflow/shared.js +66 -30
  52. package/dist/commands/workflow/shared.js.map +1 -1
  53. package/dist/commands/workflow/status.d.ts +5 -2
  54. package/dist/commands/workflow/status.d.ts.map +1 -1
  55. package/dist/commands/workflow/status.js +62 -28
  56. package/dist/commands/workflow/status.js.map +1 -1
  57. package/dist/core/archive.d.ts +38 -0
  58. package/dist/core/archive.d.ts.map +1 -1
  59. package/dist/core/archive.js +492 -75
  60. package/dist/core/archive.js.map +1 -1
  61. package/dist/core/artifact-graph/index.d.ts +2 -2
  62. package/dist/core/artifact-graph/index.d.ts.map +1 -1
  63. package/dist/core/artifact-graph/index.js +2 -2
  64. package/dist/core/artifact-graph/index.js.map +1 -1
  65. package/dist/core/artifact-graph/instruction-loader.d.ts +8 -0
  66. package/dist/core/artifact-graph/instruction-loader.d.ts.map +1 -1
  67. package/dist/core/artifact-graph/instruction-loader.js +58 -36
  68. package/dist/core/artifact-graph/instruction-loader.js.map +1 -1
  69. package/dist/core/artifact-graph/resolver.d.ts +39 -12
  70. package/dist/core/artifact-graph/resolver.d.ts.map +1 -1
  71. package/dist/core/artifact-graph/resolver.js +82 -36
  72. package/dist/core/artifact-graph/resolver.js.map +1 -1
  73. package/dist/core/artifact-graph/schema.d.ts +24 -0
  74. package/dist/core/artifact-graph/schema.d.ts.map +1 -1
  75. package/dist/core/artifact-graph/schema.js +32 -1
  76. package/dist/core/artifact-graph/schema.js.map +1 -1
  77. package/dist/core/artifact-graph/stub-detection.d.ts +10 -2
  78. package/dist/core/artifact-graph/stub-detection.d.ts.map +1 -1
  79. package/dist/core/artifact-graph/stub-detection.js +18 -11
  80. package/dist/core/artifact-graph/stub-detection.js.map +1 -1
  81. package/dist/core/artifact-graph/types.d.ts +2 -2
  82. package/dist/core/artifact-graph/types.d.ts.map +1 -1
  83. package/dist/core/artifact-graph/types.js +10 -1
  84. package/dist/core/artifact-graph/types.js.map +1 -1
  85. package/dist/core/change-metadata/schema.d.ts.map +1 -1
  86. package/dist/core/change-metadata/schema.js +18 -4
  87. package/dist/core/change-metadata/schema.js.map +1 -1
  88. package/dist/core/change-presenter.d.ts.map +1 -1
  89. package/dist/core/change-presenter.js +13 -8
  90. package/dist/core/change-presenter.js.map +1 -1
  91. package/dist/core/change-status-policy.d.ts.map +1 -1
  92. package/dist/core/change-status-policy.js +3 -1
  93. package/dist/core/change-status-policy.js.map +1 -1
  94. package/dist/core/codex-metrics.d.ts +1 -1
  95. package/dist/core/codex-metrics.js +1 -1
  96. package/dist/core/config-schema.d.ts +8 -0
  97. package/dist/core/config-schema.d.ts.map +1 -1
  98. package/dist/core/config-schema.js +10 -0
  99. package/dist/core/config-schema.js.map +1 -1
  100. package/dist/core/dashboard-activity.d.ts +4 -4
  101. package/dist/core/dashboard-activity.js +4 -4
  102. package/dist/core/dashboard-data.d.ts +11 -5
  103. package/dist/core/dashboard-data.d.ts.map +1 -1
  104. package/dist/core/dashboard-data.js +54 -28
  105. package/dist/core/dashboard-data.js.map +1 -1
  106. package/dist/core/dashboard-hub.d.ts +3 -3
  107. package/dist/core/dashboard-hub.d.ts.map +1 -1
  108. package/dist/core/dashboard-hub.js +16 -4
  109. package/dist/core/dashboard-hub.js.map +1 -1
  110. package/dist/core/dashboard-routes.d.ts +2 -1
  111. package/dist/core/dashboard-routes.d.ts.map +1 -1
  112. package/dist/core/dashboard-routes.js +102 -33
  113. package/dist/core/dashboard-routes.js.map +1 -1
  114. package/dist/core/global-config.d.ts +71 -2
  115. package/dist/core/global-config.d.ts.map +1 -1
  116. package/dist/core/global-config.js +149 -4
  117. package/dist/core/global-config.js.map +1 -1
  118. package/dist/core/id.d.ts +9 -0
  119. package/dist/core/id.d.ts.map +1 -1
  120. package/dist/core/id.js +37 -0
  121. package/dist/core/id.js.map +1 -1
  122. package/dist/core/init.d.ts +9 -2
  123. package/dist/core/init.d.ts.map +1 -1
  124. package/dist/core/init.js +116 -33
  125. package/dist/core/init.js.map +1 -1
  126. package/dist/core/list.d.ts.map +1 -1
  127. package/dist/core/list.js +69 -45
  128. package/dist/core/list.js.map +1 -1
  129. package/dist/core/local-server.d.ts +9 -2
  130. package/dist/core/local-server.d.ts.map +1 -1
  131. package/dist/core/local-server.js +24 -4
  132. package/dist/core/local-server.js.map +1 -1
  133. package/dist/core/markdown-render.d.ts.map +1 -1
  134. package/dist/core/markdown-render.js +7 -2
  135. package/dist/core/markdown-render.js.map +1 -1
  136. package/dist/core/migrate.d.ts +24 -2
  137. package/dist/core/migrate.d.ts.map +1 -1
  138. package/dist/core/migrate.js +335 -59
  139. package/dist/core/migrate.js.map +1 -1
  140. package/dist/core/parsers/change-parser.d.ts +20 -1
  141. package/dist/core/parsers/change-parser.d.ts.map +1 -1
  142. package/dist/core/parsers/change-parser.js +76 -73
  143. package/dist/core/parsers/change-parser.js.map +1 -1
  144. package/dist/core/parsers/markdown-parser.d.ts +24 -0
  145. package/dist/core/parsers/markdown-parser.d.ts.map +1 -1
  146. package/dist/core/parsers/markdown-parser.js +65 -10
  147. package/dist/core/parsers/markdown-parser.js.map +1 -1
  148. package/dist/core/parsers/requirement-blocks.d.ts +127 -6
  149. package/dist/core/parsers/requirement-blocks.d.ts.map +1 -1
  150. package/dist/core/parsers/requirement-blocks.js +349 -56
  151. package/dist/core/parsers/requirement-blocks.js.map +1 -1
  152. package/dist/core/parsers/requirement-text.d.ts +25 -1
  153. package/dist/core/parsers/requirement-text.d.ts.map +1 -1
  154. package/dist/core/parsers/requirement-text.js +62 -6
  155. package/dist/core/parsers/requirement-text.js.map +1 -1
  156. package/dist/core/parsers/spec-structure.d.ts.map +1 -1
  157. package/dist/core/parsers/spec-structure.js +36 -24
  158. package/dist/core/parsers/spec-structure.js.map +1 -1
  159. package/dist/core/project-config.d.ts +9 -2
  160. package/dist/core/project-config.d.ts.map +1 -1
  161. package/dist/core/project-config.js +30 -7
  162. package/dist/core/project-config.js.map +1 -1
  163. package/dist/core/project-layout.d.ts +26 -0
  164. package/dist/core/project-layout.d.ts.map +1 -1
  165. package/dist/core/project-layout.js +51 -1
  166. package/dist/core/project-layout.js.map +1 -1
  167. package/dist/core/schema-names.d.ts +17 -0
  168. package/dist/core/schema-names.d.ts.map +1 -1
  169. package/dist/core/schema-names.js +24 -0
  170. package/dist/core/schema-names.js.map +1 -1
  171. package/dist/core/shared/index.d.ts +1 -1
  172. package/dist/core/shared/index.d.ts.map +1 -1
  173. package/dist/core/shared/index.js +1 -1
  174. package/dist/core/shared/index.js.map +1 -1
  175. package/dist/core/shared/rules-generation.d.ts +12 -0
  176. package/dist/core/shared/rules-generation.d.ts.map +1 -1
  177. package/dist/core/shared/rules-generation.js +26 -2
  178. package/dist/core/shared/rules-generation.js.map +1 -1
  179. package/dist/core/shared/skill-generation.d.ts +7 -0
  180. package/dist/core/shared/skill-generation.d.ts.map +1 -1
  181. package/dist/core/shared/skill-generation.js +19 -0
  182. package/dist/core/shared/skill-generation.js.map +1 -1
  183. package/dist/core/shared/tool-detection.d.ts +10 -1
  184. package/dist/core/shared/tool-detection.d.ts.map +1 -1
  185. package/dist/core/shared/tool-detection.js +37 -6
  186. package/dist/core/shared/tool-detection.js.map +1 -1
  187. package/dist/core/spec-presenter.d.ts.map +1 -1
  188. package/dist/core/spec-presenter.js +23 -1
  189. package/dist/core/spec-presenter.js.map +1 -1
  190. package/dist/core/specs-apply.d.ts +98 -1
  191. package/dist/core/specs-apply.d.ts.map +1 -1
  192. package/dist/core/specs-apply.js +426 -63
  193. package/dist/core/specs-apply.js.map +1 -1
  194. package/dist/core/templates/fragments/change-diff.d.ts +37 -0
  195. package/dist/core/templates/fragments/change-diff.d.ts.map +1 -0
  196. package/dist/core/templates/fragments/change-diff.js +37 -0
  197. package/dist/core/templates/fragments/change-diff.js.map +1 -0
  198. package/dist/core/templates/fragments/sync-fail.d.ts +8 -0
  199. package/dist/core/templates/fragments/sync-fail.d.ts.map +1 -0
  200. package/dist/core/templates/fragments/sync-fail.js +8 -0
  201. package/dist/core/templates/fragments/sync-fail.js.map +1 -0
  202. package/dist/core/templates/fragments/validate.d.ts +14 -1
  203. package/dist/core/templates/fragments/validate.d.ts.map +1 -1
  204. package/dist/core/templates/fragments/validate.js +14 -1
  205. package/dist/core/templates/fragments/validate.js.map +1 -1
  206. package/dist/core/templates/fragments/verify.d.ts +2 -2
  207. package/dist/core/templates/fragments/verify.d.ts.map +1 -1
  208. package/dist/core/templates/fragments/verify.js +8 -5
  209. package/dist/core/templates/fragments/verify.js.map +1 -1
  210. package/dist/core/templates/workflows/apply.d.ts +1 -1
  211. package/dist/core/templates/workflows/apply.d.ts.map +1 -1
  212. package/dist/core/templates/workflows/apply.js +29 -10
  213. package/dist/core/templates/workflows/apply.js.map +1 -1
  214. package/dist/core/templates/workflows/archive.d.ts.map +1 -1
  215. package/dist/core/templates/workflows/archive.js +27 -9
  216. package/dist/core/templates/workflows/archive.js.map +1 -1
  217. package/dist/core/templates/workflows/decision.d.ts.map +1 -1
  218. package/dist/core/templates/workflows/decision.js +10 -4
  219. package/dist/core/templates/workflows/decision.js.map +1 -1
  220. package/dist/core/templates/workflows/explore.d.ts +2 -2
  221. package/dist/core/templates/workflows/explore.d.ts.map +1 -1
  222. package/dist/core/templates/workflows/explore.js +7 -3
  223. package/dist/core/templates/workflows/explore.js.map +1 -1
  224. package/dist/core/templates/workflows/grill.d.ts +2 -2
  225. package/dist/core/templates/workflows/grill.d.ts.map +1 -1
  226. package/dist/core/templates/workflows/grill.js +5 -4
  227. package/dist/core/templates/workflows/grill.js.map +1 -1
  228. package/dist/core/templates/workflows/issue.d.ts.map +1 -1
  229. package/dist/core/templates/workflows/issue.js +9 -3
  230. package/dist/core/templates/workflows/issue.js.map +1 -1
  231. package/dist/core/templates/workflows/propose.d.ts.map +1 -1
  232. package/dist/core/templates/workflows/propose.js +4 -1
  233. package/dist/core/templates/workflows/propose.js.map +1 -1
  234. package/dist/core/templates/workflows/sync.d.ts.map +1 -1
  235. package/dist/core/templates/workflows/sync.js +25 -11
  236. package/dist/core/templates/workflows/sync.js.map +1 -1
  237. package/dist/core/templates/workflows/update.d.ts.map +1 -1
  238. package/dist/core/templates/workflows/update.js +17 -10
  239. package/dist/core/templates/workflows/update.js.map +1 -1
  240. package/dist/core/update.d.ts +5 -0
  241. package/dist/core/update.d.ts.map +1 -1
  242. package/dist/core/update.js +66 -29
  243. package/dist/core/update.js.map +1 -1
  244. package/dist/core/validation/constants.d.ts +7 -1
  245. package/dist/core/validation/constants.d.ts.map +1 -1
  246. package/dist/core/validation/constants.js +16 -2
  247. package/dist/core/validation/constants.js.map +1 -1
  248. package/dist/core/validation/purpose-placeholder.d.ts.map +1 -1
  249. package/dist/core/validation/purpose-placeholder.js +35 -11
  250. package/dist/core/validation/purpose-placeholder.js.map +1 -1
  251. package/dist/core/validation/section-validator.d.ts +7 -0
  252. package/dist/core/validation/section-validator.d.ts.map +1 -1
  253. package/dist/core/validation/section-validator.js +22 -2
  254. package/dist/core/validation/section-validator.js.map +1 -1
  255. package/dist/core/validation/sister-changes.d.ts +93 -0
  256. package/dist/core/validation/sister-changes.d.ts.map +1 -0
  257. package/dist/core/validation/sister-changes.js +180 -0
  258. package/dist/core/validation/sister-changes.js.map +1 -0
  259. package/dist/core/validation/task-markers.d.ts +9 -0
  260. package/dist/core/validation/task-markers.d.ts.map +1 -0
  261. package/dist/core/validation/task-markers.js +71 -0
  262. package/dist/core/validation/task-markers.js.map +1 -0
  263. package/dist/core/validation/types.d.ts +58 -0
  264. package/dist/core/validation/types.d.ts.map +1 -1
  265. package/dist/core/validation/types.js +22 -0
  266. package/dist/core/validation/types.js.map +1 -1
  267. package/dist/core/validation/validator.d.ts +79 -2
  268. package/dist/core/validation/validator.d.ts.map +1 -1
  269. package/dist/core/validation/validator.js +565 -84
  270. package/dist/core/validation/validator.js.map +1 -1
  271. package/dist/utils/change-metadata.d.ts +62 -5
  272. package/dist/utils/change-metadata.d.ts.map +1 -1
  273. package/dist/utils/change-metadata.js +193 -31
  274. package/dist/utils/change-metadata.js.map +1 -1
  275. package/dist/utils/change-utils.d.ts +21 -0
  276. package/dist/utils/change-utils.d.ts.map +1 -1
  277. package/dist/utils/change-utils.js +168 -53
  278. package/dist/utils/change-utils.js.map +1 -1
  279. package/dist/utils/command-line.d.ts +11 -0
  280. package/dist/utils/command-line.d.ts.map +1 -0
  281. package/dist/utils/command-line.js +43 -0
  282. package/dist/utils/command-line.js.map +1 -0
  283. package/dist/utils/display-width.d.ts +10 -0
  284. package/dist/utils/display-width.d.ts.map +1 -0
  285. package/dist/utils/display-width.js +15 -0
  286. package/dist/utils/display-width.js.map +1 -0
  287. package/dist/utils/file-system.d.ts +16 -0
  288. package/dist/utils/file-system.d.ts.map +1 -1
  289. package/dist/utils/file-system.js +49 -2
  290. package/dist/utils/file-system.js.map +1 -1
  291. package/dist/utils/frontmatter.d.ts.map +1 -1
  292. package/dist/utils/frontmatter.js +11 -5
  293. package/dist/utils/frontmatter.js.map +1 -1
  294. package/dist/utils/interactive.d.ts.map +1 -1
  295. package/dist/utils/interactive.js +3 -1
  296. package/dist/utils/interactive.js.map +1 -1
  297. package/dist/utils/item-discovery.d.ts +3 -2
  298. package/dist/utils/item-discovery.d.ts.map +1 -1
  299. package/dist/utils/item-discovery.js +34 -16
  300. package/dist/utils/item-discovery.js.map +1 -1
  301. package/dist/utils/link.d.ts +0 -1
  302. package/dist/utils/link.d.ts.map +1 -1
  303. package/dist/utils/link.js +0 -1
  304. package/dist/utils/link.js.map +1 -1
  305. package/dist/utils/match.d.ts.map +1 -1
  306. package/dist/utils/match.js +10 -1
  307. package/dist/utils/match.js.map +1 -1
  308. package/dist/utils/option-flags.d.ts +9 -0
  309. package/dist/utils/option-flags.d.ts.map +1 -0
  310. package/dist/utils/option-flags.js +12 -0
  311. package/dist/utils/option-flags.js.map +1 -0
  312. package/dist/utils/sentence.d.ts +9 -0
  313. package/dist/utils/sentence.d.ts.map +1 -0
  314. package/dist/utils/sentence.js +12 -0
  315. package/dist/utils/sentence.js.map +1 -0
  316. package/dist/utils/spec-files.d.ts +84 -1
  317. package/dist/utils/spec-files.d.ts.map +1 -1
  318. package/dist/utils/spec-files.js +192 -3
  319. package/dist/utils/spec-files.js.map +1 -1
  320. package/dist/utils/task-progress.d.ts.map +1 -1
  321. package/dist/utils/task-progress.js +32 -9
  322. package/dist/utils/task-progress.js.map +1 -1
  323. package/dist/utils/timestamp.d.ts +27 -0
  324. package/dist/utils/timestamp.d.ts.map +1 -1
  325. package/dist/utils/timestamp.js +37 -0
  326. package/dist/utils/timestamp.js.map +1 -1
  327. package/package.json +4 -1
  328. package/schemas/decision/templates/decision.md +2 -2
  329. package/schemas/issue/schema.yaml +12 -6
  330. package/schemas/issue/templates/task.md +1 -1
  331. package/schemas/sdd/schema.yaml +21 -10
  332. package/schemas/sdd/templates/proposal.md +1 -1
@@ -34,6 +34,15 @@ export declare const MAX_CHANGE_NAME_LENGTH = 100;
34
34
  * what `completeRootStructure` creates and what `createChange` refuses agree.
35
35
  */
36
36
  export declare const ARCHIVE_DIR_NAME = "archive";
37
+ /**
38
+ * Asked by every resolver that turns a name into a change directory. The
39
+ * archive directory passes the other two tests a resolver applies — the name
40
+ * is kebab-case and the directory exists — so without this `status` reported
41
+ * it as a change and `archive` tried to move it into itself.
42
+ */
43
+ export declare function isReservedChangeName(name: string): boolean;
44
+ /** Why the name is refused; each caller adds what to do instead. */
45
+ export declare const RESERVED_CHANGE_NAME_REASON = "'archive' is a reserved directory name under tospec/changes/ \u2014 it holds every archived change";
37
46
  /**
38
47
  * The shared kebab-id grammar. A leading digit is allowed so orderings like
39
48
  * `100-add-feature` work.
@@ -41,6 +50,18 @@ export declare const ARCHIVE_DIR_NAME = "archive";
41
50
  * @param noun User-facing name for the identifier in validation errors.
42
51
  */
43
52
  export declare function validateChangeName(name: string, noun?: string): ValidationResult;
53
+ /**
54
+ * `validateChangeName` plus the portability rule capability folders follow, for
55
+ * a command about to create a name. `nul` or `con` passes the kebab grammar, but
56
+ * Windows cannot open such a directory, so git there cannot index or check out
57
+ * the change. Applied on every OS, as the repo is shared across them.
58
+ *
59
+ * Kept out of `validateChangeName`, which also resolves existing changes: a
60
+ * `nul` change made on Linux, or before this rule, would then be refused by
61
+ * `status --change` and `instructions` and left with no way forward but a
62
+ * manual rename.
63
+ */
64
+ export declare function validateNewChangeName(name: string, noun?: string): ValidationResult;
44
65
  /**
45
66
  * Bring a tospec root up to the full layout every command expects.
46
67
  *
@@ -1 +1 @@
1
- {"version":3,"file":"change-utils.d.ts","sourceRoot":"","sources":["../../src/utils/change-utils.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAYvE,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC;IAC/D,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAgB,GAAG,gBAAgB,CA2CvF;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrG;AAED,+EAA+E;AAC/E,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAyE7B"}
1
+ {"version":3,"file":"change-utils.d.ts","sourceRoot":"","sources":["../../src/utils/change-utils.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAcvE,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC;IAC/D,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,uGAA8G,CAAC;AAEvJ;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAgB,GAAG,gBAAgB,CA2CvF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAgB,GAAG,gBAAgB,CAQ1F;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAcrG;AAED,+EAA+E;AAC/E,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAqG7B"}
@@ -1,13 +1,16 @@
1
1
  import path from 'path';
2
2
  import { promises as fsPromises } from 'fs';
3
3
  import { FileSystemUtils } from './file-system.js';
4
- import { formatTimestamp, formatLocalDate } from './timestamp.js';
4
+ import { formatTimestamp, formatLocalDateTime } from './timestamp.js';
5
5
  import { writeChangeMetadata, validateSchemaName } from './change-metadata.js';
6
6
  import { readProjectConfig, resolveConfigFileInDir } from '../core/project-config.js';
7
- import { isKebabId } from '../core/id.js';
7
+ import { isKebabId, portableNameFault } from '../core/id.js';
8
8
  import { resolveSchema, loadTemplate } from '../core/artifact-graph/index.js';
9
+ import { assertChangeSchema } from '../core/schema-names.js';
9
10
  import { findTicketPath } from './item-discovery.js';
10
- import { stripBom } from '../core/parsers/requirement-text.js';
11
+ import { findLayoutPathNotDirectory } from '../core/project-layout.js';
12
+ import { stripBom, toSingleLine } from '../core/parsers/requirement-text.js';
13
+ import { sectionHeaderKey } from '../core/parsers/requirement-blocks.js';
11
14
  const DEFAULT_SCHEMA = 'sdd';
12
15
  // sdd → requirement, issue → issue; custom schemas leave type unset.
13
16
  const SCHEMA_TO_CHANGE_TYPE = {
@@ -24,6 +27,17 @@ export const MAX_CHANGE_NAME_LENGTH = 100;
24
27
  * what `completeRootStructure` creates and what `createChange` refuses agree.
25
28
  */
26
29
  export const ARCHIVE_DIR_NAME = 'archive';
30
+ /**
31
+ * Asked by every resolver that turns a name into a change directory. The
32
+ * archive directory passes the other two tests a resolver applies — the name
33
+ * is kebab-case and the directory exists — so without this `status` reported
34
+ * it as a change and `archive` tried to move it into itself.
35
+ */
36
+ export function isReservedChangeName(name) {
37
+ return name === ARCHIVE_DIR_NAME;
38
+ }
39
+ /** Why the name is refused; each caller adds what to do instead. */
40
+ export const RESERVED_CHANGE_NAME_REASON = `'${ARCHIVE_DIR_NAME}' is a reserved directory name under tospec/changes/ — it holds every archived change`;
27
41
  /**
28
42
  * The shared kebab-id grammar. A leading digit is allowed so orderings like
29
43
  * `100-add-feature` work.
@@ -70,6 +84,27 @@ export function validateChangeName(name, noun = 'Change name') {
70
84
  }
71
85
  return { valid: true };
72
86
  }
87
+ /**
88
+ * `validateChangeName` plus the portability rule capability folders follow, for
89
+ * a command about to create a name. `nul` or `con` passes the kebab grammar, but
90
+ * Windows cannot open such a directory, so git there cannot index or check out
91
+ * the change. Applied on every OS, as the repo is shared across them.
92
+ *
93
+ * Kept out of `validateChangeName`, which also resolves existing changes: a
94
+ * `nul` change made on Linux, or before this rule, would then be refused by
95
+ * `status --change` and `instructions` and left with no way forward but a
96
+ * manual rename.
97
+ */
98
+ export function validateNewChangeName(name, noun = 'Change name') {
99
+ const validation = validateChangeName(name, noun);
100
+ if (!validation.valid)
101
+ return validation;
102
+ const fault = portableNameFault(name);
103
+ if (fault !== undefined) {
104
+ return { valid: false, error: `${noun} "${name}" ${fault}; pick another name` };
105
+ }
106
+ return { valid: true };
107
+ }
73
108
  /**
74
109
  * Bring a tospec root up to the full layout every command expects.
75
110
  *
@@ -80,8 +115,15 @@ export function validateChangeName(name, noun = 'Change name') {
80
115
  */
81
116
  export async function completeRootStructure(projectRoot, defaultSchema) {
82
117
  const tospecDir = path.join(projectRoot, 'tospec');
83
- await FileSystemUtils.createDirectory(path.join(tospecDir, 'specs'));
84
- await FileSystemUtils.createDirectory(path.join(tospecDir, 'changes', ARCHIVE_DIR_NAME));
118
+ const dirs = [path.join(tospecDir, 'specs'), path.join(tospecDir, 'changes', ARCHIVE_DIR_NAME)];
119
+ // Both checked before either is made, so a refusal leaves nothing half-built.
120
+ for (const dir of dirs) {
121
+ const occupied = findLayoutPathNotDirectory(projectRoot, dir);
122
+ if (occupied)
123
+ throw occupied;
124
+ }
125
+ for (const dir of dirs)
126
+ await FileSystemUtils.createDirectory(dir);
85
127
  // The config records the project default schema, never a one-off override,
86
128
  // and is written only when none exists.
87
129
  if (!resolveConfigFileInDir(tospecDir)) {
@@ -90,33 +132,64 @@ export async function completeRootStructure(projectRoot, defaultSchema) {
90
132
  }
91
133
  /** Creates `tospec/changes/<name>/` with its metadata file and ticket stub. */
92
134
  export async function createChange(projectRoot, name, options = {}) {
93
- const validation = validateChangeName(name);
135
+ const validation = validateNewChangeName(name);
94
136
  if (!validation.valid) {
95
137
  throw new Error(validation.error);
96
138
  }
97
139
  const defaultSchema = options.defaultSchema ?? DEFAULT_SCHEMA;
98
140
  // Schema: explicit option → project config → supplied default.
99
141
  let schemaName;
142
+ let schemaFromConfig = false;
100
143
  if (options.schema) {
101
144
  schemaName = options.schema;
102
145
  }
103
146
  else {
104
147
  try {
105
- const config = readProjectConfig(projectRoot);
106
- schemaName = config?.schema ?? defaultSchema;
148
+ const configured = readProjectConfig(projectRoot)?.schema;
149
+ schemaFromConfig = configured !== undefined;
150
+ schemaName = configured ?? defaultSchema;
107
151
  }
108
152
  catch {
109
153
  schemaName = defaultSchema;
110
154
  }
111
155
  }
112
- validateSchemaName(schemaName, projectRoot);
156
+ // Every check `new change --schema` applies, whichever source named the
157
+ // schema: a config naming `decision`, or a schema.yaml that does not parse,
158
+ // otherwise created a change that apply reported blocked or that nothing
159
+ // could read.
160
+ let schema;
161
+ try {
162
+ validateSchemaName(schemaName, projectRoot);
163
+ assertChangeSchema(schemaName);
164
+ schema = resolveSchema(schemaName, projectRoot);
165
+ }
166
+ catch (error) {
167
+ if (!schemaFromConfig)
168
+ throw error;
169
+ // The reader typed no schema, so name where this one came from.
170
+ const message = error instanceof Error ? error.message : String(error);
171
+ throw new Error(`${message} (schema '${schemaName}' comes from tospec/config.yaml; fix its 'schema:' field, or pass --schema <name>)`);
172
+ }
113
173
  const changeDir = path.join(options.changesDir ?? path.join(projectRoot, 'tospec', 'changes'), name);
114
174
  // Before the existence test below, which would otherwise answer "Change
115
175
  // 'archive' already exists" and send the reader to delete every archived
116
176
  // change. Not in validateChangeName: that is shared with decision topics,
117
177
  // where the name is fine.
118
- if (name === ARCHIVE_DIR_NAME) {
119
- throw new Error(`'${ARCHIVE_DIR_NAME}' is a reserved directory name under tospec/changes/ — it holds every archived change. Pick another change name.`);
178
+ if (isReservedChangeName(name)) {
179
+ throw new Error(`${RESERVED_CHANGE_NAME_REASON}. Pick another change name.`);
180
+ }
181
+ // Every directory the writes below create into, checked before the first
182
+ // one: a file at any of them otherwise surfaced as mkdir's bare `ENOTDIR`.
183
+ const tospecDir = path.join(projectRoot, 'tospec');
184
+ for (const dir of [
185
+ changeDir,
186
+ path.join(tospecDir, 'specs'),
187
+ path.join(tospecDir, 'changes', ARCHIVE_DIR_NAME),
188
+ path.join(tospecDir, 'tickets'),
189
+ ]) {
190
+ const occupied = findLayoutPathNotDirectory(projectRoot, dir);
191
+ if (occupied)
192
+ throw occupied;
120
193
  }
121
194
  if (await FileSystemUtils.directoryExists(changeDir)) {
122
195
  throw new Error(`Change '${name}' already exists at ${changeDir}`);
@@ -128,17 +201,16 @@ export async function createChange(projectRoot, name, options = {}) {
128
201
  // valid for every other change.
129
202
  try {
130
203
  await completeRootStructure(projectRoot, defaultSchema);
131
- const today = formatLocalDate();
132
204
  writeChangeMetadata(changeDir, {
133
205
  schema: schemaName,
134
206
  type: SCHEMA_TO_CHANGE_TYPE[schemaName],
135
- created: today,
207
+ created: formatLocalDateTime(),
136
208
  ...options.metadata,
137
209
  }, projectRoot);
138
210
  // The stamped filename is CLI-generated and recorded nowhere an agent reads,
139
211
  // so the path has to come back or filling in the Summary means globbing for
140
212
  // a filename the CLI just chose.
141
- const ticket = await writeTicketStub(projectRoot, name, schemaName, options.description);
213
+ const ticket = await writeTicketStub(projectRoot, name, schemaName, schema, options.description);
142
214
  return {
143
215
  schema: schemaName,
144
216
  changeDir,
@@ -153,22 +225,53 @@ export async function createChange(projectRoot, name, options = {}) {
153
225
  throw error;
154
226
  }
155
227
  }
156
- /** `## Summary` followed by the template's `[...]` placeholder. */
157
- const PLACEHOLDER_SUMMARY = /(##[ \t]*Summary[ \t]*\r?\n)\[[^\]]*\]/;
228
+ /**
229
+ * A `##` line followed by the template's `[...]` placeholder. Whether that line
230
+ * is `## Summary` is left to `sectionHeaderKey`, the delta parser's reading: a
231
+ * regex of its own took `##Summary`, which is no heading, and missed
232
+ * `## Summary ##`.
233
+ */
234
+ const PLACEHOLDER_AFTER_SECTION = /^(##[^\r\n]*)(\r?\n)\[[^\]]*\]/gm;
235
+ /** The text with its placeholder Summary filled in, or null when it has none. */
236
+ function fillPlaceholderSummary(text, summary) {
237
+ for (const match of text.matchAll(PLACEHOLDER_AFTER_SECTION)) {
238
+ if (sectionHeaderKey(match[1]) !== 'summary')
239
+ continue;
240
+ const start = match.index;
241
+ return text.slice(0, start) + match[1] + match[2] + summary + text.slice(start + match[0].length);
242
+ }
243
+ return null;
244
+ }
245
+ /** A leading `---` fence pair; the block between them is captured with its endings. */
246
+ const TICKET_FRONTMATTER = /^(---\r?\n)([\s\S]*?\r?\n)?(---(?:\r?\n|$))/;
247
+ /**
248
+ * The text with each named frontmatter key's value replaced. Only keys already
249
+ * present are rewritten, and only inside the frontmatter, so a `ref:` line in
250
+ * the body stays as written. Line endings survive because the per-key pattern
251
+ * stops at `\r` or `\n`.
252
+ */
253
+ function rewriteTicketHeader(text, fields) {
254
+ const match = TICKET_FRONTMATTER.exec(text);
255
+ if (!match?.[2])
256
+ return text;
257
+ let block = match[2];
258
+ for (const [key, value] of Object.entries(fields)) {
259
+ // A function replacement, so `$`-sequences in the value stay literal.
260
+ block = block.replace(new RegExp(`^(${key}:)[^\\r\\n]*`, 'm'), (_, prefix) => `${prefix} ${value}`);
261
+ }
262
+ return match[1] + block + match[3] + text.slice(match[0].length);
263
+ }
158
264
  /**
159
265
  * Writes a stub into the global `tospec/tickets/<yyyyMMdd_HHmmss>-<name>.md`
160
266
  * index: a yaml header generated here plus the schema's `ticket.md` body.
161
267
  * `change:` links back to the change; `ref` points at where its detail lives. A
162
268
  * schema without a `ticket.md` template opts out of the index.
163
269
  */
164
- async function writeTicketStub(projectRoot, name, schemaName, description) {
165
- let schema;
166
- try {
167
- schema = resolveSchema(schemaName, projectRoot);
168
- }
169
- catch {
170
- return undefined; // schema unresolvable — nothing to scaffold
171
- }
270
+ async function writeTicketStub(projectRoot, name, schemaName,
271
+ // Resolved by the caller, which refuses an unloadable schema before creating
272
+ // anything: swallowing the parse error here once created a change with no
273
+ // ticket and no word about why.
274
+ schema, description) {
172
275
  // A schema opts into the global ticket index by shipping a ticket.md template.
173
276
  let body;
174
277
  try {
@@ -179,37 +282,13 @@ async function writeTicketStub(projectRoot, name, schemaName, description) {
179
282
  // `--description` has nowhere to land. Report the drop.
180
283
  return description?.trim() ? { ticketsUnsupported: true } : undefined;
181
284
  }
182
- // A function replacer keeps `$`-sequences in the description literal.
183
- const summary = description?.trim();
285
+ // Spliced in, not passed to `replace`, so `$`-sequences in the description
286
+ // stay literal. Folded to one line, so a second line cannot open a heading or
287
+ // a `---` rule below `## Summary`.
288
+ const summary = description === undefined ? undefined : toSingleLine(description);
184
289
  if (summary) {
185
- body = body.replace(PLACEHOLDER_SUMMARY, (_m, head) => head + summary);
290
+ body = fillPlaceholderSummary(body, summary) ?? body;
186
291
  }
187
- // The index holds one active ticket per change. `rm -rf` on a change leaves
188
- // its ticket behind, and recreating the name would otherwise write a second:
189
- // archive files under the older, and the newer stays active forever naming a
190
- // dead path.
191
- const existing = await findTicketPath(projectRoot, name);
192
- if (existing) {
193
- // Filled in only when the Summary is still the placeholder. A written
194
- // Summary is kept and reported rather than overwritten.
195
- if (summary) {
196
- // Stripped before the rewrite: the BOM would otherwise survive into a
197
- // file tospec is re-emitting, which ships UTF-8 without one.
198
- const current = await fsPromises
199
- .readFile(existing, 'utf-8')
200
- .then(stripBom)
201
- .catch(() => null);
202
- if (current !== null && PLACEHOLDER_SUMMARY.test(current)) {
203
- await FileSystemUtils.writeFile(existing, current.replace(PLACEHOLDER_SUMMARY, (_m, head) => head + summary));
204
- }
205
- else {
206
- return { path: existing, summaryKept: true };
207
- }
208
- }
209
- return { path: existing };
210
- }
211
- const stamp = formatTimestamp(new Date());
212
- const ticketPath = path.join(projectRoot, 'tospec', 'tickets', `${stamp}-${name}.md`);
213
292
  // Root-relative so it stays stable once the ticket moves to tospec/tickets/archive/.
214
293
  //
215
294
  // The schema's own first non-glob artifact, not a hardcoded proposal.md /
@@ -226,6 +305,42 @@ async function writeTicketStub(projectRoot, name, schemaName, description) {
226
305
  // the same vocabulary as .tospec.yaml and `list --json`; the schema name has
227
306
  // its own key so neither means two things.
228
307
  const changeType = SCHEMA_TO_CHANGE_TYPE[schemaName] ?? schemaName;
308
+ // The index holds one active ticket per change. `rm -rf` on a change leaves
309
+ // its ticket behind, and recreating the name would otherwise write a second:
310
+ // archive files under the older, and the newer stays active forever naming a
311
+ // dead path.
312
+ const existing = await findTicketPath(projectRoot, name);
313
+ if (existing) {
314
+ // Stripped before the rewrite: the BOM would otherwise survive into a
315
+ // file tospec is re-emitting, which ships UTF-8 without one.
316
+ const current = await fsPromises
317
+ .readFile(existing, 'utf-8')
318
+ .then(stripBom)
319
+ .catch(() => null);
320
+ if (current === null)
321
+ return { path: existing, ...(summary ? { summaryKept: true } : {}) };
322
+ // The header describes the change, and the change was just recreated: a
323
+ // ticket kept from an sdd attempt went on saying `schema: sdd` for an
324
+ // issue change, and archive then pointed `ref:` at a proposal.md the
325
+ // archived directory never had.
326
+ let updated = rewriteTicketHeader(current, { type: changeType, schema: schemaName, ref });
327
+ // Filled in only when the Summary is still the placeholder. A written
328
+ // Summary is kept and reported rather than overwritten.
329
+ let summaryKept = false;
330
+ if (summary) {
331
+ const filled = fillPlaceholderSummary(updated, summary);
332
+ if (filled !== null)
333
+ updated = filled;
334
+ else
335
+ summaryKept = true;
336
+ }
337
+ if (updated !== current) {
338
+ await FileSystemUtils.writeFile(existing, updated);
339
+ }
340
+ return { path: existing, ...(summaryKept ? { summaryKept: true } : {}) };
341
+ }
342
+ const stamp = formatTimestamp(new Date());
343
+ const ticketPath = path.join(projectRoot, 'tospec', 'tickets', `${stamp}-${name}.md`);
229
344
  const header = `---\ntitle: ${name}\ndate: "${stamp}"\ntype: ${changeType}\nschema: ${schemaName}\nchange: ${name}\nref: ${ref}\n---\n\n`;
230
345
  await FileSystemUtils.createDirectory(path.join(projectRoot, 'tospec', 'tickets'));
231
346
  await FileSystemUtils.writeFile(ticketPath, header + body);
@@ -1 +1 @@
1
- {"version":3,"file":"change-utils.js","sourceRoot":"","sources":["../../src/utils/change-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"change-utils.js","sourceRoot":"","sources":["../../src/utils/change-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Splits an `$EDITOR`-style value into argv: whitespace separates words, and
3
+ * single or double quotes group a word that contains spaces
4
+ * (`"C:\Program Files\Editor\editor.exe" --wait`).
5
+ *
6
+ * Backslash is deliberately not an escape: on Windows it is the path
7
+ * separator, and treating it as one turns `C:\tools\vim.exe` into
8
+ * `C:toolsvim.exe`. No shell is involved, so nothing else is special.
9
+ */
10
+ export declare function splitCommandLine(value: string): string[];
11
+ //# sourceMappingURL=command-line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-line.d.ts","sourceRoot":"","sources":["../../src/utils/command-line.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BxD"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Splits an `$EDITOR`-style value into argv: whitespace separates words, and
3
+ * single or double quotes group a word that contains spaces
4
+ * (`"C:\Program Files\Editor\editor.exe" --wait`).
5
+ *
6
+ * Backslash is deliberately not an escape: on Windows it is the path
7
+ * separator, and treating it as one turns `C:\tools\vim.exe` into
8
+ * `C:toolsvim.exe`. No shell is involved, so nothing else is special.
9
+ */
10
+ export function splitCommandLine(value) {
11
+ const words = [];
12
+ let current = '';
13
+ let inWord = false;
14
+ let quote = null;
15
+ for (const char of value) {
16
+ if (quote) {
17
+ if (char === quote)
18
+ quote = null;
19
+ else
20
+ current += char;
21
+ continue;
22
+ }
23
+ if (char === '"' || char === "'") {
24
+ quote = char;
25
+ inWord = true;
26
+ continue;
27
+ }
28
+ if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
29
+ if (inWord) {
30
+ words.push(current);
31
+ current = '';
32
+ inWord = false;
33
+ }
34
+ continue;
35
+ }
36
+ current += char;
37
+ inWord = true;
38
+ }
39
+ if (inWord)
40
+ words.push(current);
41
+ return words;
42
+ }
43
+ //# sourceMappingURL=command-line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-line.js","sourceRoot":"","sources":["../../src/utils/command-line.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,KAAK,GAAqB,IAAI,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,IAAI,KAAK,KAAK;gBAAE,KAAK,GAAG,IAAI,CAAC;;gBAC5B,OAAO,IAAI,IAAI,CAAC;YACrB,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjC,KAAK,GAAG,IAAI,CAAC;YACb,MAAM,GAAG,IAAI,CAAC;YACd,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACpE,IAAI,MAAM,EAAE,CAAC;gBACX,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACpB,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,KAAK,CAAC;YACjB,CAAC;YACD,SAAS;QACX,CAAC;QACD,OAAO,IAAI,IAAI,CAAC;QAChB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Pads to a terminal column count. `String.prototype.padEnd` counts UTF-16
3
+ * units, so a CJK name (two columns per character) pushed every later column
4
+ * of its row out of line. Capability ids and project directory names are free
5
+ * text, so the human tables that print them pad here instead.
6
+ */
7
+ export declare function padEndDisplay(text: string, width: number): string;
8
+ /** Widest entry in terminal columns, for sizing a column passed to `padEndDisplay`. */
9
+ export declare function maxDisplayWidth(texts: readonly string[]): number;
10
+ //# sourceMappingURL=display-width.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-width.d.ts","sourceRoot":"","sources":["../../src/utils/display-width.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEhE"}
@@ -0,0 +1,15 @@
1
+ import stringWidth from 'fast-string-width';
2
+ /**
3
+ * Pads to a terminal column count. `String.prototype.padEnd` counts UTF-16
4
+ * units, so a CJK name (two columns per character) pushed every later column
5
+ * of its row out of line. Capability ids and project directory names are free
6
+ * text, so the human tables that print them pad here instead.
7
+ */
8
+ export function padEndDisplay(text, width) {
9
+ return text + ' '.repeat(Math.max(0, width - stringWidth(text)));
10
+ }
11
+ /** Widest entry in terminal columns, for sizing a column passed to `padEndDisplay`. */
12
+ export function maxDisplayWidth(texts) {
13
+ return texts.reduce((max, text) => Math.max(max, stringWidth(text)), 0);
14
+ }
15
+ //# sourceMappingURL=display-width.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-width.js","sourceRoot":"","sources":["../../src/utils/display-width.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAa;IACvD,OAAO,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,KAAwB;IACtD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1E,CAAC"}
@@ -1,3 +1,4 @@
1
+ import * as nodeFs from 'fs';
1
2
  /**
2
3
  * Most-recent mtime of any file under `dirPath`, falling back to the directory's
3
4
  * own mtime when it holds none. Shared by `tospec list --sort recent` and the
@@ -20,6 +21,21 @@ export declare function extractNameFromPath(filePath: string): string;
20
21
  * directory use `isAbsentDirectoryError`: the two differ on `ENOTDIR`.
21
22
  */
22
23
  export declare function isMissingPathError(error: unknown): boolean;
24
+ /**
25
+ * True for a real directory and for a symlink or junction that resolves to one.
26
+ * The one rule for "is this entry a directory" when deciding which changes,
27
+ * specs and deltas exist: `Dirent.isDirectory()` reports the raw entry type, and
28
+ * Windows reports a junction as a symlink, so `list` and `validate` skipped a
29
+ * linked change that `status` (which stats the path) worked on, and archive
30
+ * left a linked capability's delta unmerged without a word.
31
+ */
32
+ export declare function isDirectoryEntry(parentDir: string, entry: nodeFs.Dirent): boolean;
33
+ /**
34
+ * Records `dir` by its real path for a recursive scan that follows directory
35
+ * links; false when the scan already entered it (or it cannot be resolved).
36
+ * Without it a link back to an ancestor recurses until the path is too long.
37
+ */
38
+ export declare function enterOnce(visited: Set<string>, dir: string): Promise<boolean>;
23
39
  /**
24
40
  * Narrower than `isMissingPathError`: `ENOTDIR` from a `readdir` means a
25
41
  * non-directory occupies the path, and answering "empty" makes a broken layout
@@ -1 +1 @@
1
- {"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../../src/utils/file-system.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCpE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE9D;AAED,qBAAa,eAAe;IAC1B,yDAAyD;IACzD,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpC;IAED,mEAAmE;IACnE,MAAM,CAAC,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAW1D;IAED,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAIhC,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAMhC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAe/D;IAED,OAAa,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3D;IAED,OAAa,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU1D;IAED,OAAa,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU9D;IAED,OAAa,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvE;IAED,OAAa,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEvD;IAED,OAAa,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiCrE;CACF"}
1
+ {"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../../src/utils/file-system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,IAAI,CAAC;AAK7B;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CpE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG1D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,GAAG,OAAO,CASjF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUnF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE9D;AAED,qBAAa,eAAe;IAC1B,yDAAyD;IACzD,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpC;IAED,mEAAmE;IACnE,MAAM,CAAC,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAW1D;IAED,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAIhC,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAMhC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAe/D;IAED,OAAa,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3D;IAED,OAAa,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU1D;IAED,OAAa,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU9D;IAED,OAAa,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvE;IAED,OAAa,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEvD;IAED,OAAa,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiCrE;CACF"}
@@ -12,7 +12,11 @@ export async function getLastModified(dirPath) {
12
12
  // fatal: the dashboard runs this on every save, and an editor's atomic save
13
13
  // (write a temp file, rename it over) is exactly that race — one ENOENT used
14
14
  // to fail the whole overview, and `list` with it.
15
+ const visited = new Set();
15
16
  async function walk(dir, isRoot) {
17
+ // The root goes on even when unresolvable, so readdir reports why below.
18
+ if (!(await enterOnce(visited, dir)) && !isRoot)
19
+ return;
16
20
  let entries;
17
21
  try {
18
22
  entries = await fs.readdir(dir, { withFileTypes: true });
@@ -26,7 +30,7 @@ export async function getLastModified(dirPath) {
26
30
  // stats fan out rather than running one await at a time.
27
31
  await Promise.all(entries.map(async (entry) => {
28
32
  const full = path.join(dir, entry.name);
29
- if (entry.isDirectory()) {
33
+ if (isDirectoryEntry(dir, entry)) {
30
34
  await walk(full, false);
31
35
  return;
32
36
  }
@@ -35,7 +39,11 @@ export async function getLastModified(dirPath) {
35
39
  ({ mtimeMs } = await fs.stat(full));
36
40
  }
37
41
  catch (error) {
38
- if (isMissingPathError(error))
42
+ // A link that resolves to itself (ELOOP) has no mtime to offer, and
43
+ // an unrelated broken link made the whole change unreadable in `list`
44
+ // and the dashboard. Tolerated here only: `isMissingPathError` callers
45
+ // read it as "absent", which ELOOP is not.
46
+ if (isMissingPathError(error) || error?.code === 'ELOOP')
39
47
  return;
40
48
  throw error;
41
49
  }
@@ -75,6 +83,45 @@ export function isMissingPathError(error) {
75
83
  const code = error?.code;
76
84
  return code === 'ENOENT' || code === 'ENOTDIR';
77
85
  }
86
+ /**
87
+ * True for a real directory and for a symlink or junction that resolves to one.
88
+ * The one rule for "is this entry a directory" when deciding which changes,
89
+ * specs and deltas exist: `Dirent.isDirectory()` reports the raw entry type, and
90
+ * Windows reports a junction as a symlink, so `list` and `validate` skipped a
91
+ * linked change that `status` (which stats the path) worked on, and archive
92
+ * left a linked capability's delta unmerged without a word.
93
+ */
94
+ export function isDirectoryEntry(parentDir, entry) {
95
+ if (entry.isDirectory())
96
+ return true;
97
+ if (!entry.isSymbolicLink())
98
+ return false;
99
+ try {
100
+ return nodeFs.statSync(path.join(parentDir, entry.name)).isDirectory();
101
+ }
102
+ catch {
103
+ // Dangling or looping: there is no directory to read behind it.
104
+ return false;
105
+ }
106
+ }
107
+ /**
108
+ * Records `dir` by its real path for a recursive scan that follows directory
109
+ * links; false when the scan already entered it (or it cannot be resolved).
110
+ * Without it a link back to an ancestor recurses until the path is too long.
111
+ */
112
+ export async function enterOnce(visited, dir) {
113
+ let real;
114
+ try {
115
+ real = await fs.realpath(dir);
116
+ }
117
+ catch {
118
+ return false;
119
+ }
120
+ if (visited.has(real))
121
+ return false;
122
+ visited.add(real);
123
+ return true;
124
+ }
78
125
  /**
79
126
  * Narrower than `isMissingPathError`: `ENOTDIR` from a `readdir` means a
80
127
  * non-directory occupies the path, and answering "empty" makes a broken layout