@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
package/README.md CHANGED
@@ -1,144 +1,132 @@
1
1
  # tospec
2
2
 
3
- > Spec-driven development CLI — 用 schema 定義文件與流程, 讓每個開發階段都能被檢查. 進度由檔案推算, 工作方法寫在 Skill 裡.
3
+ > 用 schema 定義文件與流程的 spec-driven development CLI. 進度由檔案推算, 工作方法寫在 Skill 裡.
4
4
 
5
- tospec 把需求釐清, 規格, 設計, 任務, 實作到歸檔串成一套工作流程. Skill 協助 AI 工具 (Claude Code / Codex) 處理各階段, CLI 負責建立檔案, 檢查狀態與驗證規格格式. 它不另外維護狀態資料庫; `status` 會依 change 目錄裡有哪些檔案, 推算目前進度.
5
+ 寫需求時最常遇到的問題不是「不會寫」, 而是「寫到一半就跳去實作, 最後規格跟程式對不上」. tospec 把釐清需求, 寫規格, 設計, 拆任務, 實作, 歸檔串成一條線: Skill 帶著 AI 工具 (Claude Code / Codex) 走每一步, CLI 負責建檔, 看狀態, 驗證格式.
6
+
7
+ 它沒有狀態資料庫. `tospec status` 看 change 目錄裡有哪些檔案, 就知道走到哪一步; 檔案出現, 狀態就前進.
6
8
 
7
9
  ## 安裝
8
10
 
9
- 需要 Node.js `>=22.22.0`.
11
+ 需要 Node.js 22.22.0 以上.
10
12
 
11
13
  ```bash
12
14
  npm install -g @seanmars/tospec
13
- ```
14
-
15
- 安裝後即可使用 `tospec` 指令:
16
-
17
- ```bash
18
15
  tospec --help
19
- tospec --version
20
16
  ```
21
17
 
22
- 也可以不安裝, 直接用 `npx`:
23
-
24
- ```bash
25
- npx @seanmars/tospec --help
26
- ```
18
+ 不想全域安裝也可以直接 `npx @seanmars/tospec --help`.
27
19
 
28
20
  ## 快速開始
29
21
 
30
22
  ```bash
31
- # 1. 在專案根目錄初始化, 並安裝 Claude Code 的 Skill
23
+ # 初始化專案, 順便裝好 Claude Code 的 Skill
32
24
  tospec init --tools claude
33
25
 
34
- # 2. 建立一個新需求 change
26
+ # 開一個新需求
35
27
  tospec new change add-dark-mode --schema sdd
36
28
 
37
- # 3. 查看目前各文件的狀態
29
+ # 看這個 change 走到哪了
38
30
  tospec status --change add-dark-mode
39
31
 
40
- # 4. 驗證文件格式
32
+ # 檢查文件格式
41
33
  tospec validate add-dark-mode
42
34
 
43
- # 5. 完成後歸檔, 把規格合併進主 specs
35
+ # 做完了, 把規格合併進主 specs 並歸檔
44
36
  tospec archive add-dark-mode
45
37
  ```
46
38
 
47
- `--tools` 可填 `claude`, `agents`, `all` 或 `none`. Skill 一律先寫入 `.agents/`, 各工具目錄再以連結指向它, 因此 `claude` 隱含包含 `agents`; Codex 直接讀取 `.agents/skills/`, 不需要也不會產生 `.codex/` 目錄. `none` 完全不產生 agent 內容, 只建立 `tospec/` 目錄結構, 與互動選單中不選取任何項目等價. 初始化後 Claude Code 另外會產生 `/tosx:<name>` 快捷指令.
39
+ `--tools` 可填 `claude`, `agents`, `all` 或 `none`. Skill 一律先寫進 `.agents/skills/` 這份 canonical 副本, 再複製到各工具目錄, 所以 `claude` 隱含 `agents`. Codex 直接讀 `.agents/`, 不會另外產生 `.codex/`. `none` 只建 `tospec/` 目錄, 不碰任何 agent 內容.
48
40
 
49
- `.claude/skills/tospec-*` 是指向 `.agents/skills/tospec-*` 的連結 (Windows 用 junction, 其他平台用相對 symlink), 所以修改 `.agents/` 下的 skill 會立即對每個工具生效. 若平台拒絕建立連結 (Windows 未開啟開發者模式、部分網路磁碟或容器檔案系統), init 會改為複製並在輸出中指明 — 此時修改 canonical skill 後需重跑 `tospec update` 才會同步. 規則檔不共用連結, 每個目標各自持有一份完整檔案.
41
+ `.claude/skills/` 是複本不是連結, 因為 junction 與 symlink 進 git 的記錄方式不同, 會讓追蹤內容取決於貢獻者的作業系統. 改了 `.agents/skills/` 之後要跑 `tospec update` 才會同步過去.
50
42
 
51
43
  ## 兩種工作流程
52
44
 
53
- 建立 change 時用 `--schema` 選擇流程:
45
+ 開 change 時用 `--schema` 選:
54
46
 
55
47
  | schema | 用途 | 文件流程 |
56
48
  |--------|------|----------|
57
49
  | `sdd` | 開發新需求 | `proposal → specs / design → tasks` |
58
- | `issue` | 修正問題 | `task`(根因診斷) + 選配 `specs` |
50
+ | `issue` | 修正問題 | `task` (根因診斷) + 選配 `specs` |
59
51
 
60
- 兩者都在 **apply** 階段實作, 最後由 **archive** 判斷是否需要先 **sync** 再歸檔. apply 以完整測試與 `tospec validate` 通過為完成標準; **verify (雙軸審查) 是 opt-in**, 只有使用者主動要求時才執行, apply 不會自己跑, 也不會主動詢問.
52
+ 兩者都在 **apply** 階段實作, 最後由 **archive** 判斷要不要先 **sync** 再歸檔. apply 的完成標準是測試與 `tospec validate` 通過; 雙軸審查 (verify) 是 opt-in, 使用者開口才做.
61
53
 
62
- 文件狀態的判斷方式:
54
+ 文件狀態只有四種:
63
55
 
64
- - `done` — 對應檔案已存在
65
- - `ready` — 前置文件都已建立, 這份還沒有, 可以開始
66
- - `blocked` — 至少一個前置文件還沒建立
67
- - `skipped` — 選配文件未建立, 不阻擋流程
56
+ - `done`: 檔案已存在
57
+ - `ready`: 前置文件都齊了, 這份還沒寫, 可以開始
58
+ - `blocked`: 至少一份前置文件還沒建立
59
+ - `skipped`: 選配文件沒建, 不擋流程
68
60
 
69
- ## Skill 工作流程
61
+ ## Skill
70
62
 
71
- 工作方法寫在 Skill 裡, CLI 只負責檔案與驗證. `tospec init` 會安裝 10 個 workflow Skill:
63
+ `tospec init` 會裝 10 個 workflow Skill, Claude Code 另外會有對應的 `/tosx:<name>` 快捷指令.
72
64
 
73
65
  | Skill | 作用 |
74
66
  |-------|------|
75
- | `tospec-explore` | 以訪談收斂還很模糊的需求或問題 |
76
- | `tospec-grill` | 對任何產出 (計畫/決策/設計) 做四象限壓力測試 |
77
- | `tospec-propose` | 把已討論清楚的需求整理成完整 sdd change |
78
- | `tospec-issue` | 診斷 bug 至根因, 產出 issue change |
79
- | `tospec-decision` | 記錄架構決策為永久 ADR |
67
+ | `tospec-explore` | 用訪談收斂還很模糊的需求或問題 |
68
+ | `tospec-grill` | 對計畫, 決策, 設計做壓力測試 |
69
+ | `tospec-propose` | 把討論清楚的需求整理成完整的 sdd change |
70
+ | `tospec-issue` | 診斷 bug 到根因, 產出 issue change |
71
+ | `tospec-decision` | 把架構決策記成永久 ADR |
80
72
  | `tospec-update` | 修訂 change 的規劃文件並保持一致 |
81
- | `tospec-apply` | 逐項實作任務 (不強制寫測試); verify 需使用者主動要求 |
73
+ | `tospec-apply` | 逐項實作任務 |
82
74
  | `tospec-apply-with-tdd` | 同上, 但強制先寫測試 (red → green) |
83
75
  | `tospec-sync` | 以程式碼為準核對規格, 產出 sync-report |
84
- | `tospec-archive` | 判斷是否需要 sync, 然後歸檔完成的 change |
76
+ | `tospec-archive` | 判斷要不要 sync, 然後歸檔 |
85
77
 
86
- 典型流程: `explore` (想清楚) → `propose` (寫成 change) → `apply` (實作) → `sync` (需要時核對規格) → `archive` (歸檔). 修 bug 則從 `issue` 開始, 走同樣的 apply → archive 收尾.
78
+ 典型流程: `explore` 想清楚, `propose` 寫成 change, `apply` 實作, 需要時 `sync` 核對規格, 最後 `archive`. 修 bug 從 `issue` 開始, 一樣走 apply → archive 收尾.
87
79
 
88
80
  ## CLI 指令
89
81
 
90
- 多數指令支援 `--json`, 方便 AI 工具讀取結果.
82
+ 多數指令支援 `--json`, 給 AI 工具讀. 封包格式與 exit code 見 [Agent 契約](./docs/agent-contract.md).
91
83
 
92
84
  ### 專案管理
93
85
 
94
- | 指令 | 作用 |
95
- |------|------|
96
- | `tospec init [path]` | 初始化專案, 建立 `tospec/`, Skill 與 workflow 規則. 選項: `--tools <claude\|agents\|all\|none>`, `--force` (不略過規則衝突), `--profile <name>` |
97
- | `tospec update [path]` | 重新產生已設定的 Skill, 修復連結或複製檔案, 並同步刷新 workflow 規則. 選項: `--force` (不略過規則衝突) |
98
- | `tospec rules [path]` | 只為已安裝 Skill 的工具新增或更新 workflow 規則檔, 不動 Skill/commands/設定 |
99
- | `tospec migrate [openspec-dir]` | 把 OpenSpec 專案轉成 tospec 格式 (預設讀 `./openspec`). 選項: `-f, --force` |
100
- | `tospec config <sub>` | 全域設定. 子命令: `path`, `list`, `get <key>`, `set <key> <value>`, `unset <key>`, `reset`, `edit`, `profile [preset]` (調整要安裝的 Skill) |
86
+ | 指令 | 作用 | 選項 |
87
+ |------|------|------|
88
+ | `tospec init [path]` | 初始化專案, 建立 `tospec/`, Skill 與 workflow 規則 | `--tools`, `--force`, `--profile <name>`, `--json` |
89
+ | `tospec update [path]` | 重新產生 Skill 並同步到各工具目錄 | `--force`, `--json` |
90
+ | `tospec rules [path]` | 只刷新 workflow 規則檔, 不動 Skill 與設定 | `--json` |
91
+ | `tospec migrate [openspec-dir]` | 把 OpenSpec 專案轉成 tospec 格式 (預設讀 `./openspec`) | `-f, --force`, `--json` |
92
+ | `tospec config <sub>` | 全域設定: `path`, `list`, `get`, `set`, `unset`, `reset`, `edit`, `profile [preset]` | 各子命令多支援 `--json` |
101
93
 
102
- `init`, `rules`, `update` 三個入口共用同一份 workflow 規則: 內容固定來自套件內的 `assets/rules/tospec/single-sourc-of-truth.md`, 不受專案 schema 或已安裝 workflow 影響, 分別寫入 `.agents/rules/tospec/single-sourc-of-truth.md` 與 `.claude/rules/tospec/single-sourc-of-truth.md`, 與既有 `rules/tospec/decision.md` 並存, 不覆寫. 產出檔內含版本標記與內容雜湊, 用來分辨「套件升級」與「使用者手改」: 一旦偵測到手改或格式異常, 三個入口都會在寫入任何專案檔案前整次失敗, `--force` 也不例外; 解法是自行保留修改內容, 刪除該規則檔後重跑.
103
-
104
- `.codex/rules/` 已不再是規則目標: tospec 不讀也不寫該目錄, 因此使用者對其中檔案的修改不再阻擋任何命令. `.codex` 下既有的內容不會被刪除或搬移, init 與 update 只會提示可自行移除. 規則 Markdown 一律視為參考文件: Codex 不會自動載入 `.agents/rules/` 下的 Markdown, 它的文字指引來自 `AGENTS.md` 與 skill 檔, 載入方式需自行處理, tospec 不會修改 `AGENTS.md` 或 `config.toml`.
94
+ workflow 規則檔 (`.agents/rules/tospec/single-source-of-truth.md` 與 `.claude/` 下的複本) 由套件產生, 內含版本標記與內容雜湊. 一旦偵測到手改, `init` / `update` / `rules` 都會在寫入任何檔案前整次失敗, `--force` 也不例外. 想保留修改, 先備份再刪掉該檔重跑.
105
95
 
106
96
  ### 建立與查詢
107
97
 
108
- | 指令 | 作用 |
109
- |------|------|
110
- | `tospec new change <name>` | 建立 change 目錄與 ticket 索引檔. 選項: `--schema <sdd\|issue>`, `--description <text>`, `--goal <text>`, `--decisions <files>`, `--json` |
111
- | `tospec list` | 列出進行中的 change (預設). 選項: `--specs`, `--changes`, `--sort <recent\|name>`, `--type <requirement\|issue>`, `--json` |
112
- | `tospec show [item-name]` | 顯示 change 或 spec 內容. 選項: `--type <change\|spec>`, `--deltas-only`, `--requirements`, `--no-scenarios`, `-r, --requirement <id>`, `--no-interactive`, `--json` |
113
- | `tospec status` | 依檔案與 schema 顯示各文件狀態. 選項: `--change <id>`, `--schema <name>`, `--json` |
114
- | `tospec decision new <topic>` | 建立 ADR (`tospec/decisions/<yyyyMMdd_HHmmss>-<topic>.md`) 與索引列. 選項: `--title <text>`, `--summary <text>`, `--date <yyyyMMdd_HHmmss>`, `--status <proposed\|accepted\|superseded>`, `--force`, `--json` |
115
- | `tospec decision list` | 以索引表列出 ADR. 選項: `--status <proposed\|accepted\|superseded>`, `--sort <date\|name>`, `--json` |
116
- | `tospec skill-metrics` | 開啟本機網頁, 以圖表呈現每個 Skill 的耗時. 選項: `--no-open` |
117
-
118
- `tospec skill-metrics` 會在 loopback 上啟動一台伺服器, 印出網址、開啟瀏覽器, 並停在前景直到 Ctrl+C. 連接埠固定從 **26693** 開始; 若已被占用則自動往上遞增直到找到可用的, 所以再開一個也不會失敗. 網頁是唯一的輸出形式, 沒有表格也沒有 `--json`; `--no-open` 只印網址而不開瀏覽器, 供沒有瀏覽器的環境使用.
98
+ | 指令 | 作用 | 選項 |
99
+ |------|------|------|
100
+ | `tospec new change <name>` | 建立 change 目錄與 ticket | `--schema <sdd\|issue>`, `--description`, `--goal`, `--decisions <files>`, `--json` |
101
+ | `tospec list` | 列出進行中的 change | `--specs`, `--changes`, `--sort <recent\|name>`, `--type <requirement\|issue>`, `--json` |
102
+ | `tospec show [item-name]` | 顯示 change 或 spec | `--type <change\|spec>`, `--diff`, `--requirements`, `--no-scenarios`, `-r <id>`, `--no-interactive`, `--json` |
103
+ | `tospec status` | 顯示各文件狀態 | `--change <id>`, `--all`, `--schema <name>`, `--json` |
104
+ | `tospec decision new <topic>` | 建立 ADR 與索引列 | `--title`, `--summary`, `--date`, `--status`, `--force`, `--json` |
105
+ | `tospec decision list` | 列出 ADR | `--status`, `--sort <date\|name>`, `--reindex`, `--json` |
106
+ | `tospec skill-metrics` | 開本機網頁看每個 Skill 的耗時 | `--no-open` |
119
107
 
120
- 頁面共五張圖: 各 Skill 的總投入時間 (實色為 engaged, 凹陷部分為 idle, 整根長度即 span)、典型的單次時長 (engaged 與 span 的中位數)、每次執行的分佈 (每一次 run 都是一個點)、每日投入時間, 以及執行時間軸. 總量與中位數刻意分成兩張: 一個 Skill 可能總量第一但每次都很短, 那是次數多而不是每次慢.
108
+ `show --diff` 會把 change 裡每個 requirement 對照主 specs 顯示差異, 包括 REMOVED 會刪掉的那段.
121
109
 
122
- 時間範圍、idle gap、split gap 都可在頁面上調整並即時重算, 選擇會記在瀏覽器中; 「只看 tospec workflow」單純隱藏列, 不重新計算. 右上角可切換主題與語言 (English / 正體中文), 兩者同樣會被記住. 終端機輸出維持英文, 與其他指令一致.
123
-
124
- 資料同時來自 Claude Code 與 Codex 兩種工具的紀錄, 一律唯讀且不寫入任何檔案. Claude Code 讀取 transcript 的 `attributionSkill` 欄位 (只存在於較新的 session, 舊紀錄無法回溯統計); Codex 的 session 沒有對應欄位, 因此改用推論 — 只要偵測到某個 Skill 的 `SKILL.md` 被讀取, 就視為該 Skill 開始執行. 由於 Codex 的歸屬是推論而非直接紀錄, 兩者精準度不同, 頁面上一律分開呈現、絕不合併成同一個數字, Codex 的數字並附上這項說明. 每一列的標籤結尾都會標上來源工具 (Claude/Codex), 兩者皆標而非只標其中一方, 以免另一方被讀成預設值. 頁面在統計為空時, 會分別指出兩種工具各自屬於哪一種情況.
110
+ `skill-metrics` 讀 Claude Code 與 Codex 的 session 紀錄, 只讀不寫. Claude Code 是直接讀 transcript 的歸屬欄位 (舊 session 沒有, 統計不到); Codex 沒有對應欄位, 改用「讀了哪個 `SKILL.md`」推論. 兩者精準度不同, 頁面上分開呈現, 不合併.
125
111
 
126
112
  ### 驗證與歸檔
127
113
 
128
- | 指令 | 作用 |
129
- |------|------|
130
- | `tospec validate [item-name]` | 檢查必要段落與 delta spec 格式. 選項: `--all`, `--changes`, `--specs`, `--type <change\|spec>`, `--strict`, `--concurrency <n>`, `--no-interactive`, `--json` |
131
- | `tospec archive [change-name]` | 重新驗證, 合併 delta specs 到主 specs, 再把 change 移到 archive. 選項: `-y, --yes`, `--skip-specs`, `--no-validate`, `--require-sync`, `--json` |
114
+ | 指令 | 作用 | 選項 |
115
+ |------|------|------|
116
+ | `tospec validate [item-name]` | 檢查必要段落與 delta spec 格式 | `--all`, `--changes`, `--specs`, `--type`, `--strict`, `--concurrency <n>`, `--no-interactive`, `--json` |
117
+ | `tospec archive [change-name]` | 重新驗證, 合併 delta specs, 把 change 移到 archive | `-y`, `--skip-specs`, `--no-validate`, `--require-sync`, `--json` |
118
+
119
+ delta spec 固定放在 `specs/<capability>/spec.md`, 恰好一層, 更深的目錄不會被合併. 完全沒有行為變更的 change (工具, CI, 純文件) 在 `.tospec.yaml` 設 `skip_specs: true` 就好, 不要為了過驗證捏造 requirement.
132
120
 
133
- delta spec 的位置固定為 `specs/<capability>/spec.md`, **恰好一層**: 更深的巢狀目錄不會被合併, 驗證會直接報錯. 完全沒有行為變更的 change (工具, CI, 純文件) 在 `.tospec.yaml` 設 `skip_specs: true` 宣告即可, 不要為了通過驗證捏造 requirement.
121
+ requirement 內文慣例上要有 SHALL 或 MUST, 缺了是 WARNING; `--strict` 才會把它當錯誤.
134
122
 
135
123
  ### 給 AI 工具的指令
136
124
 
137
- | 指令 | 作用 |
138
- |------|------|
139
- | `tospec instructions [artifact]` | 回傳建立文件或套用任務的完整指引 (artifact 填 `apply` 時回傳實作指引). 選項: `--change <id>`, `--schema <name>`, `--json` |
140
- | `tospec schemas` | 列出可用的工作流程 schema 與其文件. 選項: `--json` |
141
- | `tospec templates` | 顯示指定 schema 中各文件範本的實際路徑. 選項: `--schema <name>`, `--json` |
125
+ | 指令 | 作用 | 選項 |
126
+ |------|------|------|
127
+ | `tospec instructions [artifact]` | 回傳建立文件的完整指引; `artifact` 填 `apply` 回傳實作指引 | `--change <id>`, `--schema <name>`, `--json` |
128
+ | `tospec schemas` | 列出可用的 schema 與其文件 | `--json` |
129
+ | `tospec templates` | 顯示 schema 中各文件範本的路徑 | `--schema <name>`, `--json` |
142
130
 
143
131
  ### Dashboard
144
132
 
@@ -146,16 +134,15 @@ delta spec 的位置固定為 `specs/<capability>/spec.md`, **恰好一層**:
146
134
  tospec dashboard [path]
147
135
  ```
148
136
 
149
- 啟動本機唯讀 web dashboard, 檢視 change 與 specs 進度. 選項: `-p, --port <n>` (預設 5620), `--host <addr>` (預設 127.0.0.1), `-o, --open` (啟動後開啟瀏覽器), `-d, --detach` (背景執行), `--stop` (停止本專案的 dashboard), `-l, --list` (列出所有執行中的 dashboard), `--allow-remote` (允許綁定非 loopback 位址, 會對外網開放).
137
+ 本機 web dashboard, 看 change 與 specs 進度. 唯一的寫入是勾 task checkbox, 已歸檔或 sync 通過的 change 不能勾.
150
138
 
151
- ## 文件
152
-
153
- - [Agent 契約](./docs/agent-contract.md) —— `--json` 的成功/失敗封包與 exit code
154
- - [自訂 schema](./docs/custom-schema.md) —— `schema.yaml` 欄位, 解析順序, 佈局限制
139
+ 選項: `-p, --port <n>` (預設 5620), `--host <addr>` (預設 127.0.0.1), `-o, --open`, `-d, --detach`, `--stop`, `-l, --list`, `--allow-remote` (綁非 loopback 位址, 會對外網開放).
155
140
 
156
- ## 更新日誌
141
+ ## 文件
157
142
 
158
- 各版本的變更與其根因說明: [CHANGELOG.md](./CHANGELOG.md)
143
+ - [Agent 契約](./docs/agent-contract.md): `--json` 的成功/失敗封包與 exit code
144
+ - [自訂 schema](./docs/custom-schema.md): `schema.yaml` 欄位, 解析順序, 佈局限制
145
+ - [CHANGELOG](./CHANGELOG.md): 各版本的變更與根因說明
159
146
 
160
147
  ## 授權
161
148
 
@@ -587,6 +587,10 @@ function updateHealthStrip(staleDays) {
587
587
  if (parseErrors) {
588
588
  items.push(healthItem(`${parseErrors} ticket parse error(s)`, 'tickets-panel'));
589
589
  }
590
+ const unreadable = overview.changes.filter((c) => c.unreadable).length;
591
+ if (unreadable) {
592
+ items.push(healthItem(`${unreadable} change(s) with unreadable metadata`, 'changes-panel'));
593
+ }
590
594
  if (activity && activity.available && activity.specDrift) {
591
595
  items.push(el('span', { class: 'health-item', text: 'spec drift: code moved, tospec/ did not (7d)' }));
592
596
  }
@@ -614,6 +618,13 @@ function changeRow(c, staleDays, changed) {
614
618
  row.classList.add('row-ready');
615
619
  row.append(el('span', { class: 'badge badge-ready', text: 'ready' }));
616
620
  }
621
+ if (c.unreadable) {
622
+ // Ahead of every other badge: the counts beside it were all computed from
623
+ // metadata that would not parse, so they are zeros, not measurements.
624
+ const badge = el('span', { class: 'badge badge-unreadable', text: 'unreadable' });
625
+ badge.title = c.unreadable;
626
+ row.append(badge);
627
+ }
617
628
  if (c.artifactSummary.blocked > 0) {
618
629
  row.append(el('span', { class: 'badge badge-blocked-warn', text: 'blocked' }));
619
630
  }
@@ -840,7 +851,7 @@ function fileAccordion(file) {
840
851
  body.textContent = 'Loading...';
841
852
  try {
842
853
  const data = await api('/api/render?file=' + encodeURIComponent(file.path));
843
- body.innerHTML = data.html; // controlled container; server-rendered markdown
854
+ body.innerHTML = data.html; // sanitized by core/markdown-render.ts - raw HTML is escaped there, not here
844
855
  } catch (e) {
845
856
  loaded = false;
846
857
  body.textContent = 'Failed to render (' + (e.status || 'error') + ').';
@@ -1008,7 +1019,7 @@ async function renderSpecDetail(id) {
1008
1019
 
1009
1020
  try {
1010
1021
  const data = await api('/api/render?file=' + encodeURIComponent(`tospec/specs/${id}/spec.md`));
1011
- body.innerHTML = data.html; // controlled container; server-rendered markdown
1022
+ body.innerHTML = data.html; // sanitized by core/markdown-render.ts - raw HTML is escaped there, not here
1012
1023
  } catch {
1013
1024
  body.textContent = 'Failed to render spec.';
1014
1025
  }
@@ -1063,7 +1074,7 @@ async function renderDecisionContent(pane, file) {
1063
1074
  );
1064
1075
  try {
1065
1076
  const data = await api('/api/render?file=' + encodeURIComponent(d.path));
1066
- body.innerHTML = data.html; // controlled container; server-rendered markdown
1077
+ body.innerHTML = data.html; // sanitized by core/markdown-render.ts - raw HTML is escaped there, not here
1067
1078
  enhanceDecisionQA(body, d.content); // 決策過程 → Q/A cards (client-side, graceful fallback)
1068
1079
  } catch {
1069
1080
  body.textContent = 'Failed to render decision.';
@@ -671,6 +671,13 @@ a.row:hover {
671
671
  color: var(--error);
672
672
  }
673
673
 
674
+ /* A change whose .tospec.yaml would not parse: every count beside it is a zero
675
+ rather than a measurement, so it is marked as an error, not a progress state. */
676
+ .badge-unreadable {
677
+ background: var(--error-bg);
678
+ color: var(--error);
679
+ }
680
+
674
681
  /* -- artifact blocks & status -- */
675
682
  .blocks {
676
683
  display: inline-flex;
@@ -0,0 +1,3 @@
1
+ # Decision
2
+
3
+ Any material decision reached during discussion must be recorded with /tospec-decision, which creates a decision file and captures the relevant decision details.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAC;AAwElE,QAAA,MAAM,OAAO,SAAgB,CAAC;AAgb9B,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB,wBAAgB,MAAM,CAAC,IAAI,WAAe,GAAG,IAAI,CAchD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAgD,MAAM,WAAW,CAAC;AAmIlF,QAAA,MAAM,OAAO,SAAgB,CAAC;AA+f9B,OAAO,EAAE,OAAO,EAAE,CAAC;AAiBnB,wBAAgB,MAAM,CAAC,IAAI,WAAe,GAAG,IAAI,CAiChD"}