@matteeh/osq 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (606) hide show
  1. package/README.md +234 -15
  2. package/dist/cli/approve.d.ts +7 -0
  3. package/dist/cli/approve.d.ts.map +1 -1
  4. package/dist/cli/approve.js +34 -0
  5. package/dist/cli/approve.js.map +1 -1
  6. package/dist/cli/bin.js +2 -3
  7. package/dist/cli/bin.js.map +1 -1
  8. package/dist/cli/check.d.ts +15 -0
  9. package/dist/cli/check.d.ts.map +1 -0
  10. package/dist/cli/check.js +65 -0
  11. package/dist/cli/check.js.map +1 -0
  12. package/dist/cli/index.d.ts.map +1 -1
  13. package/dist/cli/index.js +10 -10
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/init.d.ts.map +1 -1
  16. package/dist/cli/init.js +6 -1
  17. package/dist/cli/init.js.map +1 -1
  18. package/dist/cli/lint.d.ts +3 -0
  19. package/dist/cli/lint.d.ts.map +1 -1
  20. package/dist/cli/lint.js +33 -14
  21. package/dist/cli/lint.js.map +1 -1
  22. package/dist/cli/plan-queue.d.ts +10 -4
  23. package/dist/cli/plan-queue.d.ts.map +1 -1
  24. package/dist/cli/plan-queue.js +20 -19
  25. package/dist/cli/plan-queue.js.map +1 -1
  26. package/dist/cli/plan-sections.d.ts +15 -0
  27. package/dist/cli/plan-sections.d.ts.map +1 -0
  28. package/dist/cli/plan-sections.js +47 -0
  29. package/dist/cli/plan-sections.js.map +1 -0
  30. package/dist/cli/plan.d.ts +1 -0
  31. package/dist/cli/plan.d.ts.map +1 -1
  32. package/dist/cli/plan.js +14 -4
  33. package/dist/cli/plan.js.map +1 -1
  34. package/dist/cli/report.d.ts.map +1 -1
  35. package/dist/cli/report.js +73 -1
  36. package/dist/cli/report.js.map +1 -1
  37. package/dist/cli/run.d.ts +7 -0
  38. package/dist/cli/run.d.ts.map +1 -0
  39. package/dist/cli/run.js +22 -0
  40. package/dist/cli/run.js.map +1 -0
  41. package/dist/cli/verified.d.ts +15 -0
  42. package/dist/cli/verified.d.ts.map +1 -0
  43. package/dist/cli/verified.js +34 -0
  44. package/dist/cli/verified.js.map +1 -0
  45. package/dist/core/foundation/config-agents.d.ts +16 -0
  46. package/dist/core/foundation/config-agents.d.ts.map +1 -0
  47. package/dist/core/foundation/config-agents.js +2 -0
  48. package/dist/core/foundation/config-agents.js.map +1 -0
  49. package/dist/core/foundation/config-claude.d.ts +48 -0
  50. package/dist/core/foundation/config-claude.d.ts.map +1 -0
  51. package/dist/core/foundation/config-claude.js +106 -0
  52. package/dist/core/foundation/config-claude.js.map +1 -0
  53. package/dist/core/foundation/config-codex-resolve.d.ts +10 -0
  54. package/dist/core/foundation/config-codex-resolve.d.ts.map +1 -0
  55. package/dist/core/foundation/config-codex-resolve.js +24 -0
  56. package/dist/core/foundation/config-codex-resolve.js.map +1 -0
  57. package/dist/core/foundation/config-file.d.ts +18 -0
  58. package/dist/core/foundation/config-file.d.ts.map +1 -0
  59. package/dist/core/foundation/config-file.js +46 -0
  60. package/dist/core/foundation/config-file.js.map +1 -0
  61. package/dist/core/foundation/config-gates.d.ts +2 -0
  62. package/dist/core/foundation/config-gates.d.ts.map +1 -1
  63. package/dist/core/foundation/config-gates.js +8 -0
  64. package/dist/core/foundation/config-gates.js.map +1 -1
  65. package/dist/core/foundation/config-opencode.d.ts +25 -0
  66. package/dist/core/foundation/config-opencode.d.ts.map +1 -0
  67. package/dist/core/foundation/config-opencode.js +55 -0
  68. package/dist/core/foundation/config-opencode.js.map +1 -0
  69. package/dist/core/foundation/config-pi.d.ts +10 -0
  70. package/dist/core/foundation/config-pi.d.ts.map +1 -1
  71. package/dist/core/foundation/config-pi.js +13 -0
  72. package/dist/core/foundation/config-pi.js.map +1 -1
  73. package/dist/core/foundation/config-planning.d.ts +12 -1
  74. package/dist/core/foundation/config-planning.d.ts.map +1 -1
  75. package/dist/core/foundation/config-planning.js +29 -1
  76. package/dist/core/foundation/config-planning.js.map +1 -1
  77. package/dist/core/foundation/config-traceability.d.ts +28 -0
  78. package/dist/core/foundation/config-traceability.d.ts.map +1 -0
  79. package/dist/core/foundation/config-traceability.js +63 -0
  80. package/dist/core/foundation/config-traceability.js.map +1 -0
  81. package/dist/core/foundation/config-user.d.ts +32 -0
  82. package/dist/core/foundation/config-user.d.ts.map +1 -0
  83. package/dist/core/foundation/config-user.js +2 -0
  84. package/dist/core/foundation/config-user.js.map +1 -0
  85. package/dist/core/foundation/config-vcs.d.ts +29 -0
  86. package/dist/core/foundation/config-vcs.d.ts.map +1 -0
  87. package/dist/core/foundation/config-vcs.js +57 -0
  88. package/dist/core/foundation/config-vcs.js.map +1 -0
  89. package/dist/core/foundation/config.d.ts +23 -24
  90. package/dist/core/foundation/config.d.ts.map +1 -1
  91. package/dist/core/foundation/config.js +29 -36
  92. package/dist/core/foundation/config.js.map +1 -1
  93. package/dist/core/foundation/decisions-validate.d.ts +16 -0
  94. package/dist/core/foundation/decisions-validate.d.ts.map +1 -0
  95. package/dist/core/foundation/decisions-validate.js +74 -0
  96. package/dist/core/foundation/decisions-validate.js.map +1 -0
  97. package/dist/core/foundation/decisions.d.ts +34 -0
  98. package/dist/core/foundation/decisions.d.ts.map +1 -0
  99. package/dist/core/foundation/decisions.js +152 -0
  100. package/dist/core/foundation/decisions.js.map +1 -0
  101. package/dist/core/foundation/doctor-decisions.d.ts +9 -0
  102. package/dist/core/foundation/doctor-decisions.d.ts.map +1 -0
  103. package/dist/core/foundation/doctor-decisions.js +49 -0
  104. package/dist/core/foundation/doctor-decisions.js.map +1 -0
  105. package/dist/core/foundation/doctor-managed.d.ts.map +1 -1
  106. package/dist/core/foundation/doctor-managed.js +3 -0
  107. package/dist/core/foundation/doctor-managed.js.map +1 -1
  108. package/dist/core/foundation/doctor-prices.d.ts +8 -0
  109. package/dist/core/foundation/doctor-prices.d.ts.map +1 -0
  110. package/dist/core/foundation/doctor-prices.js +25 -0
  111. package/dist/core/foundation/doctor-prices.js.map +1 -0
  112. package/dist/core/foundation/doctor.d.ts.map +1 -1
  113. package/dist/core/foundation/doctor.js +20 -30
  114. package/dist/core/foundation/doctor.js.map +1 -1
  115. package/dist/core/foundation/harness-catalog.d.ts +7 -8
  116. package/dist/core/foundation/harness-catalog.d.ts.map +1 -1
  117. package/dist/core/foundation/harness-catalog.js +26 -41
  118. package/dist/core/foundation/harness-catalog.js.map +1 -1
  119. package/dist/core/foundation/init-blocks.d.ts +1 -1
  120. package/dist/core/foundation/init-blocks.d.ts.map +1 -1
  121. package/dist/core/foundation/init-blocks.js +51 -14
  122. package/dist/core/foundation/init-blocks.js.map +1 -1
  123. package/dist/core/foundation/init.d.ts +4 -0
  124. package/dist/core/foundation/init.d.ts.map +1 -1
  125. package/dist/core/foundation/init.js +7 -0
  126. package/dist/core/foundation/init.js.map +1 -1
  127. package/dist/core/foundation/new.d.ts +4 -1
  128. package/dist/core/foundation/new.d.ts.map +1 -1
  129. package/dist/core/foundation/new.js +18 -8
  130. package/dist/core/foundation/new.js.map +1 -1
  131. package/dist/core/foundation/package-root.d.ts +6 -0
  132. package/dist/core/foundation/package-root.d.ts.map +1 -1
  133. package/dist/core/foundation/package-root.js +6 -0
  134. package/dist/core/foundation/package-root.js.map +1 -1
  135. package/dist/core/foundation/rules-block.d.ts +11 -0
  136. package/dist/core/foundation/rules-block.d.ts.map +1 -0
  137. package/dist/core/foundation/rules-block.js +90 -0
  138. package/dist/core/foundation/rules-block.js.map +1 -0
  139. package/dist/core/foundation/traceability-block.d.ts +13 -0
  140. package/dist/core/foundation/traceability-block.d.ts.map +1 -0
  141. package/dist/core/foundation/traceability-block.js +124 -0
  142. package/dist/core/foundation/traceability-block.js.map +1 -0
  143. package/dist/core/lifecycle/done.d.ts.map +1 -1
  144. package/dist/core/lifecycle/done.js +2 -4
  145. package/dist/core/lifecycle/done.js.map +1 -1
  146. package/dist/core/lifecycle/recertify.d.ts +9 -0
  147. package/dist/core/lifecycle/recertify.d.ts.map +1 -0
  148. package/dist/core/lifecycle/recertify.js +27 -0
  149. package/dist/core/lifecycle/recertify.js.map +1 -0
  150. package/dist/core/lifecycle/reject.d.ts.map +1 -1
  151. package/dist/core/lifecycle/reject.js +3 -4
  152. package/dist/core/lifecycle/reject.js.map +1 -1
  153. package/dist/core/lifecycle/retry.d.ts.map +1 -1
  154. package/dist/core/lifecycle/retry.js +6 -20
  155. package/dist/core/lifecycle/retry.js.map +1 -1
  156. package/dist/core/lifecycle/verification-record.d.ts +42 -0
  157. package/dist/core/lifecycle/verification-record.d.ts.map +1 -0
  158. package/dist/core/lifecycle/verification-record.js +76 -0
  159. package/dist/core/lifecycle/verification-record.js.map +1 -0
  160. package/dist/core/report/approval-flags.d.ts +16 -3
  161. package/dist/core/report/approval-flags.d.ts.map +1 -1
  162. package/dist/core/report/approval-flags.js +59 -22
  163. package/dist/core/report/approval-flags.js.map +1 -1
  164. package/dist/core/report/brief-to-approval.d.ts +7 -0
  165. package/dist/core/report/brief-to-approval.d.ts.map +1 -0
  166. package/dist/core/report/brief-to-approval.js +43 -0
  167. package/dist/core/report/brief-to-approval.js.map +1 -0
  168. package/dist/core/report/planning-price-gaps.d.ts +10 -0
  169. package/dist/core/report/planning-price-gaps.d.ts.map +1 -0
  170. package/dist/core/report/planning-price-gaps.js +37 -0
  171. package/dist/core/report/planning-price-gaps.js.map +1 -0
  172. package/dist/core/report/planning-slice-lookup.d.ts.map +1 -1
  173. package/dist/core/report/planning-slice-lookup.js +3 -9
  174. package/dist/core/report/planning-slice-lookup.js.map +1 -1
  175. package/dist/core/report/recent-disclosures.d.ts +18 -0
  176. package/dist/core/report/recent-disclosures.d.ts.map +1 -0
  177. package/dist/core/report/recent-disclosures.js +105 -0
  178. package/dist/core/report/recent-disclosures.js.map +1 -0
  179. package/dist/core/report/record-disclosures.d.ts +14 -0
  180. package/dist/core/report/record-disclosures.d.ts.map +1 -0
  181. package/dist/core/report/record-disclosures.js +30 -0
  182. package/dist/core/report/record-disclosures.js.map +1 -0
  183. package/dist/core/report/record-estimates.d.ts +25 -0
  184. package/dist/core/report/record-estimates.d.ts.map +1 -0
  185. package/dist/core/report/record-estimates.js +83 -0
  186. package/dist/core/report/record-estimates.js.map +1 -0
  187. package/dist/core/report/record-rework.d.ts +19 -0
  188. package/dist/core/report/record-rework.d.ts.map +1 -0
  189. package/dist/core/report/record-rework.js +50 -0
  190. package/dist/core/report/record-rework.js.map +1 -0
  191. package/dist/core/report/record-verification.d.ts +16 -0
  192. package/dist/core/report/record-verification.d.ts.map +1 -0
  193. package/dist/core/report/record-verification.js +33 -0
  194. package/dist/core/report/record-verification.js.map +1 -0
  195. package/dist/core/report/report-dependencies.d.ts +29 -0
  196. package/dist/core/report/report-dependencies.d.ts.map +1 -0
  197. package/dist/core/report/report-dependencies.js +92 -0
  198. package/dist/core/report/report-dependencies.js.map +1 -0
  199. package/dist/core/report/report-events.d.ts +1 -0
  200. package/dist/core/report/report-events.d.ts.map +1 -1
  201. package/dist/core/report/report-events.js +8 -26
  202. package/dist/core/report/report-events.js.map +1 -1
  203. package/dist/core/report/report-mutation.d.ts +34 -0
  204. package/dist/core/report/report-mutation.d.ts.map +1 -0
  205. package/dist/core/report/report-mutation.js +191 -0
  206. package/dist/core/report/report-mutation.js.map +1 -0
  207. package/dist/core/report/report-scope.d.ts +21 -0
  208. package/dist/core/report/report-scope.d.ts.map +1 -0
  209. package/dist/core/report/report-scope.js +61 -0
  210. package/dist/core/report/report-scope.js.map +1 -0
  211. package/dist/core/report/report-traceability.d.ts +29 -0
  212. package/dist/core/report/report-traceability.d.ts.map +1 -0
  213. package/dist/core/report/report-traceability.js +94 -0
  214. package/dist/core/report/report-traceability.js.map +1 -0
  215. package/dist/core/report/report.d.ts +35 -1
  216. package/dist/core/report/report.d.ts.map +1 -1
  217. package/dist/core/report/report.js +130 -111
  218. package/dist/core/report/report.js.map +1 -1
  219. package/dist/core/report/result-sections.d.ts +30 -0
  220. package/dist/core/report/result-sections.d.ts.map +1 -0
  221. package/dist/core/report/result-sections.js +125 -0
  222. package/dist/core/report/result-sections.js.map +1 -0
  223. package/dist/core/report/scope-size.d.ts +7 -0
  224. package/dist/core/report/scope-size.d.ts.map +1 -0
  225. package/dist/core/report/scope-size.js +22 -0
  226. package/dist/core/report/scope-size.js.map +1 -0
  227. package/dist/core/run/commit-message.d.ts +24 -0
  228. package/dist/core/run/commit-message.d.ts.map +1 -0
  229. package/dist/core/run/commit-message.js +76 -0
  230. package/dist/core/run/commit-message.js.map +1 -0
  231. package/dist/core/run/dead-commit.d.ts +10 -0
  232. package/dist/core/run/dead-commit.d.ts.map +1 -0
  233. package/dist/core/run/dead-commit.js +70 -0
  234. package/dist/core/run/dead-commit.js.map +1 -0
  235. package/dist/core/run/focused-tests.d.ts +43 -0
  236. package/dist/core/run/focused-tests.d.ts.map +1 -0
  237. package/dist/core/run/focused-tests.js +116 -0
  238. package/dist/core/run/focused-tests.js.map +1 -0
  239. package/dist/core/run/manifest-approval.d.ts +7 -0
  240. package/dist/core/run/manifest-approval.d.ts.map +1 -0
  241. package/dist/core/run/manifest-approval.js +30 -0
  242. package/dist/core/run/manifest-approval.js.map +1 -0
  243. package/dist/core/run/manifest.d.ts +11 -1
  244. package/dist/core/run/manifest.d.ts.map +1 -1
  245. package/dist/core/run/manifest.js +52 -11
  246. package/dist/core/run/manifest.js.map +1 -1
  247. package/dist/core/run/mutation-report.d.ts +29 -0
  248. package/dist/core/run/mutation-report.d.ts.map +1 -0
  249. package/dist/core/run/mutation-report.js +107 -0
  250. package/dist/core/run/mutation-report.js.map +1 -0
  251. package/dist/core/run/mutation-run.d.ts +32 -0
  252. package/dist/core/run/mutation-run.d.ts.map +1 -0
  253. package/dist/core/run/mutation-run.js +80 -0
  254. package/dist/core/run/mutation-run.js.map +1 -0
  255. package/dist/core/run/verification.d.ts +12 -1
  256. package/dist/core/run/verification.d.ts.map +1 -1
  257. package/dist/core/run/verification.js +24 -2
  258. package/dist/core/run/verification.js.map +1 -1
  259. package/dist/core/spec/approve-worktree-shared.d.ts +33 -0
  260. package/dist/core/spec/approve-worktree-shared.d.ts.map +1 -0
  261. package/dist/core/spec/approve-worktree-shared.js +59 -0
  262. package/dist/core/spec/approve-worktree-shared.js.map +1 -0
  263. package/dist/core/spec/approve-worktree.d.ts +21 -0
  264. package/dist/core/spec/approve-worktree.d.ts.map +1 -0
  265. package/dist/core/spec/approve-worktree.js +153 -0
  266. package/dist/core/spec/approve-worktree.js.map +1 -0
  267. package/dist/core/spec/approve.d.ts +20 -10
  268. package/dist/core/spec/approve.d.ts.map +1 -1
  269. package/dist/core/spec/approve.js +57 -54
  270. package/dist/core/spec/approve.js.map +1 -1
  271. package/dist/core/spec/capability-impact.d.ts +43 -0
  272. package/dist/core/spec/capability-impact.d.ts.map +1 -0
  273. package/dist/core/spec/capability-impact.js +85 -0
  274. package/dist/core/spec/capability-impact.js.map +1 -0
  275. package/dist/core/spec/decisions-lint.d.ts +18 -0
  276. package/dist/core/spec/decisions-lint.d.ts.map +1 -0
  277. package/dist/core/spec/decisions-lint.js +127 -0
  278. package/dist/core/spec/decisions-lint.js.map +1 -0
  279. package/dist/core/spec/delta.d.ts +6 -0
  280. package/dist/core/spec/delta.d.ts.map +1 -1
  281. package/dist/core/spec/delta.js +73 -5
  282. package/dist/core/spec/delta.js.map +1 -1
  283. package/dist/core/spec/digest-decisions.d.ts +27 -0
  284. package/dist/core/spec/digest-decisions.d.ts.map +1 -0
  285. package/dist/core/spec/digest-decisions.js +86 -0
  286. package/dist/core/spec/digest-decisions.js.map +1 -0
  287. package/dist/core/spec/digest-format.d.ts +4 -0
  288. package/dist/core/spec/digest-format.d.ts.map +1 -0
  289. package/dist/core/spec/digest-format.js +44 -0
  290. package/dist/core/spec/digest-format.js.map +1 -0
  291. package/dist/core/spec/digest.d.ts +5 -3
  292. package/dist/core/spec/digest.d.ts.map +1 -1
  293. package/dist/core/spec/digest.js +14 -33
  294. package/dist/core/spec/digest.js.map +1 -1
  295. package/dist/core/spec/human-steps.d.ts +20 -0
  296. package/dist/core/spec/human-steps.d.ts.map +1 -0
  297. package/dist/core/spec/human-steps.js +52 -0
  298. package/dist/core/spec/human-steps.js.map +1 -0
  299. package/dist/core/spec/impact-lint.d.ts +24 -0
  300. package/dist/core/spec/impact-lint.d.ts.map +1 -0
  301. package/dist/core/spec/impact-lint.js +39 -0
  302. package/dist/core/spec/impact-lint.js.map +1 -0
  303. package/dist/core/spec/import-graph.d.ts +35 -0
  304. package/dist/core/spec/import-graph.d.ts.map +1 -0
  305. package/dist/core/spec/import-graph.js +155 -0
  306. package/dist/core/spec/import-graph.js.map +1 -0
  307. package/dist/core/spec/lint-findings.d.ts +44 -0
  308. package/dist/core/spec/lint-findings.d.ts.map +1 -0
  309. package/dist/core/spec/lint-findings.js +56 -0
  310. package/dist/core/spec/lint-findings.js.map +1 -0
  311. package/dist/core/spec/lint-output.d.ts +53 -0
  312. package/dist/core/spec/lint-output.d.ts.map +1 -0
  313. package/dist/core/spec/lint-output.js +87 -0
  314. package/dist/core/spec/lint-output.js.map +1 -0
  315. package/dist/core/spec/linter.d.ts +14 -4
  316. package/dist/core/spec/linter.d.ts.map +1 -1
  317. package/dist/core/spec/linter.js +271 -111
  318. package/dist/core/spec/linter.js.map +1 -1
  319. package/dist/core/spec/merged-spec-check.d.ts +24 -0
  320. package/dist/core/spec/merged-spec-check.d.ts.map +1 -0
  321. package/dist/core/spec/merged-spec-check.js +95 -0
  322. package/dist/core/spec/merged-spec-check.js.map +1 -0
  323. package/dist/core/spec/openspec-issues.d.ts +58 -0
  324. package/dist/core/spec/openspec-issues.d.ts.map +1 -0
  325. package/dist/core/spec/openspec-issues.js +166 -0
  326. package/dist/core/spec/openspec-issues.js.map +1 -0
  327. package/dist/core/spec/parser.d.ts +1 -0
  328. package/dist/core/spec/parser.d.ts.map +1 -1
  329. package/dist/core/spec/parser.js +16 -6
  330. package/dist/core/spec/parser.js.map +1 -1
  331. package/dist/core/spec/scenario-impact.d.ts +47 -0
  332. package/dist/core/spec/scenario-impact.d.ts.map +1 -0
  333. package/dist/core/spec/scenario-impact.js +130 -0
  334. package/dist/core/spec/scenario-impact.js.map +1 -0
  335. package/dist/core/spec/test-impact.d.ts +28 -0
  336. package/dist/core/spec/test-impact.d.ts.map +1 -0
  337. package/dist/core/spec/test-impact.js +119 -0
  338. package/dist/core/spec/test-impact.js.map +1 -0
  339. package/dist/core/spec/traceability-links.d.ts +50 -0
  340. package/dist/core/spec/traceability-links.d.ts.map +1 -0
  341. package/dist/core/spec/traceability-links.js +120 -0
  342. package/dist/core/spec/traceability-links.js.map +1 -0
  343. package/dist/core/spec/traceability-lint.d.ts +29 -0
  344. package/dist/core/spec/traceability-lint.d.ts.map +1 -0
  345. package/dist/core/spec/traceability-lint.js +143 -0
  346. package/dist/core/spec/traceability-lint.js.map +1 -0
  347. package/dist/core/status/blocked-item.d.ts +8 -0
  348. package/dist/core/status/blocked-item.d.ts.map +1 -0
  349. package/dist/core/status/blocked-item.js +45 -0
  350. package/dist/core/status/blocked-item.js.map +1 -0
  351. package/dist/core/status/change-locations.d.ts +44 -0
  352. package/dist/core/status/change-locations.d.ts.map +1 -0
  353. package/dist/core/status/change-locations.js +138 -0
  354. package/dist/core/status/change-locations.js.map +1 -0
  355. package/dist/core/status/dependency-readiness.d.ts +11 -0
  356. package/dist/core/status/dependency-readiness.d.ts.map +1 -0
  357. package/dist/core/status/dependency-readiness.js +39 -0
  358. package/dist/core/status/dependency-readiness.js.map +1 -0
  359. package/dist/core/status/inbox-projection.d.ts.map +1 -1
  360. package/dist/core/status/inbox-projection.js +23 -4
  361. package/dist/core/status/inbox-projection.js.map +1 -1
  362. package/dist/core/status/inbox-text.d.ts.map +1 -1
  363. package/dist/core/status/inbox-text.js +34 -3
  364. package/dist/core/status/inbox-text.js.map +1 -1
  365. package/dist/core/status/inbox.d.ts +10 -1
  366. package/dist/core/status/inbox.d.ts.map +1 -1
  367. package/dist/core/status/inbox.js +19 -1
  368. package/dist/core/status/inbox.js.map +1 -1
  369. package/dist/core/status/layout.d.ts +6 -0
  370. package/dist/core/status/layout.d.ts.map +1 -1
  371. package/dist/core/status/layout.js +8 -0
  372. package/dist/core/status/layout.js.map +1 -1
  373. package/dist/core/status/next-step.d.ts +17 -0
  374. package/dist/core/status/next-step.d.ts.map +1 -0
  375. package/dist/core/status/next-step.js +85 -0
  376. package/dist/core/status/next-step.js.map +1 -0
  377. package/dist/core/status/pre-spawn-words.d.ts +13 -0
  378. package/dist/core/status/pre-spawn-words.d.ts.map +1 -0
  379. package/dist/core/status/pre-spawn-words.js +26 -0
  380. package/dist/core/status/pre-spawn-words.js.map +1 -0
  381. package/dist/core/status/queue-parser.d.ts +1 -0
  382. package/dist/core/status/queue-parser.d.ts.map +1 -1
  383. package/dist/core/status/queue-parser.js +41 -2
  384. package/dist/core/status/queue-parser.js.map +1 -1
  385. package/dist/core/status/queue-planning.d.ts +1 -0
  386. package/dist/core/status/queue-planning.d.ts.map +1 -1
  387. package/dist/core/status/queue-planning.js +24 -12
  388. package/dist/core/status/queue-planning.js.map +1 -1
  389. package/dist/core/status/queue-report-detail.d.ts.map +1 -1
  390. package/dist/core/status/queue-report-detail.js +5 -3
  391. package/dist/core/status/queue-report-detail.js.map +1 -1
  392. package/dist/core/status/queue-state.d.ts +1 -1
  393. package/dist/core/status/queue-state.d.ts.map +1 -1
  394. package/dist/core/status/queue-state.js +27 -41
  395. package/dist/core/status/queue-state.js.map +1 -1
  396. package/dist/core/status/show.d.ts +25 -0
  397. package/dist/core/status/show.d.ts.map +1 -1
  398. package/dist/core/status/show.js +354 -91
  399. package/dist/core/status/show.js.map +1 -1
  400. package/dist/core/status/state.d.ts.map +1 -1
  401. package/dist/core/status/state.js +1 -23
  402. package/dist/core/status/state.js.map +1 -1
  403. package/dist/core/status/status.d.ts +18 -0
  404. package/dist/core/status/status.d.ts.map +1 -1
  405. package/dist/core/status/status.js +59 -80
  406. package/dist/core/status/status.js.map +1 -1
  407. package/dist/core/status/verification.d.ts +27 -0
  408. package/dist/core/status/verification.d.ts.map +1 -0
  409. package/dist/core/status/verification.js +111 -0
  410. package/dist/core/status/verification.js.map +1 -0
  411. package/dist/core/trace/function-ranges.d.ts +30 -0
  412. package/dist/core/trace/function-ranges.d.ts.map +1 -0
  413. package/dist/core/trace/function-ranges.js +250 -0
  414. package/dist/core/trace/function-ranges.js.map +1 -0
  415. package/dist/core/trace/mutation-pick.d.ts +55 -0
  416. package/dist/core/trace/mutation-pick.d.ts.map +1 -0
  417. package/dist/core/trace/mutation-pick.js +96 -0
  418. package/dist/core/trace/mutation-pick.js.map +1 -0
  419. package/dist/core/trace/scenario-index.d.ts +27 -0
  420. package/dist/core/trace/scenario-index.d.ts.map +1 -0
  421. package/dist/core/trace/scenario-index.js +76 -0
  422. package/dist/core/trace/scenario-index.js.map +1 -0
  423. package/dist/core/trace/scenario-lookup.d.ts +14 -0
  424. package/dist/core/trace/scenario-lookup.d.ts.map +1 -0
  425. package/dist/core/trace/scenario-lookup.js +179 -0
  426. package/dist/core/trace/scenario-lookup.js.map +1 -0
  427. package/dist/core/trace/tag-scan.d.ts +44 -0
  428. package/dist/core/trace/tag-scan.d.ts.map +1 -0
  429. package/dist/core/trace/tag-scan.js +200 -0
  430. package/dist/core/trace/tag-scan.js.map +1 -0
  431. package/dist/core/vcs/doctor-git.d.ts +13 -0
  432. package/dist/core/vcs/doctor-git.d.ts.map +1 -0
  433. package/dist/core/vcs/doctor-git.js +114 -0
  434. package/dist/core/vcs/doctor-git.js.map +1 -0
  435. package/dist/core/vcs/git-vcs-write.d.ts +47 -0
  436. package/dist/core/vcs/git-vcs-write.d.ts.map +1 -0
  437. package/dist/core/vcs/git-vcs-write.js +210 -0
  438. package/dist/core/vcs/git-vcs-write.js.map +1 -0
  439. package/dist/core/vcs/git-vcs.d.ts +40 -0
  440. package/dist/core/vcs/git-vcs.d.ts.map +1 -0
  441. package/dist/core/vcs/git-vcs.js +170 -0
  442. package/dist/core/vcs/git-vcs.js.map +1 -0
  443. package/dist/core/vcs/no-vcs.d.ts +26 -0
  444. package/dist/core/vcs/no-vcs.d.ts.map +1 -0
  445. package/dist/core/vcs/no-vcs.js +62 -0
  446. package/dist/core/vcs/no-vcs.js.map +1 -0
  447. package/dist/core/vcs/select.d.ts +11 -0
  448. package/dist/core/vcs/select.d.ts.map +1 -0
  449. package/dist/core/vcs/select.js +33 -0
  450. package/dist/core/vcs/select.js.map +1 -0
  451. package/dist/core/vcs/snapshot.d.ts +34 -0
  452. package/dist/core/vcs/snapshot.d.ts.map +1 -0
  453. package/dist/core/vcs/snapshot.js +71 -0
  454. package/dist/core/vcs/snapshot.js.map +1 -0
  455. package/dist/core/vcs/vcs.d.ts +55 -0
  456. package/dist/core/vcs/vcs.d.ts.map +1 -0
  457. package/dist/core/vcs/vcs.js +2 -0
  458. package/dist/core/vcs/vcs.js.map +1 -0
  459. package/dist/core/vcs/worktree.d.ts +10 -0
  460. package/dist/core/vcs/worktree.d.ts.map +1 -0
  461. package/dist/core/vcs/worktree.js +25 -0
  462. package/dist/core/vcs/worktree.js.map +1 -0
  463. package/dist/core/web/web-data-folders.d.ts.map +1 -1
  464. package/dist/core/web/web-data-folders.js +18 -33
  465. package/dist/core/web/web-data-folders.js.map +1 -1
  466. package/dist/core/web/web-data-lifecycle.d.ts.map +1 -1
  467. package/dist/core/web/web-data-lifecycle.js +2 -1
  468. package/dist/core/web/web-data-lifecycle.js.map +1 -1
  469. package/dist/core/web/web-events.d.ts +8 -6
  470. package/dist/core/web/web-events.d.ts.map +1 -1
  471. package/dist/core/web/web-events.js +7 -31
  472. package/dist/core/web/web-events.js.map +1 -1
  473. package/dist/core/web/web-server.d.ts.map +1 -1
  474. package/dist/core/web/web-server.js +3 -0
  475. package/dist/core/web/web-server.js.map +1 -1
  476. package/dist/core/web/web-trees.d.ts +27 -0
  477. package/dist/core/web/web-trees.d.ts.map +1 -0
  478. package/dist/core/web/web-trees.js +82 -0
  479. package/dist/core/web/web-trees.js.map +1 -0
  480. package/dist/harness/claude/claude-exec-args.d.ts +13 -0
  481. package/dist/harness/claude/claude-exec-args.d.ts.map +1 -0
  482. package/dist/harness/claude/claude-exec-args.js +61 -0
  483. package/dist/harness/claude/claude-exec-args.js.map +1 -0
  484. package/dist/harness/claude/claude-exec.d.ts +12 -0
  485. package/dist/harness/claude/claude-exec.d.ts.map +1 -0
  486. package/dist/harness/claude/claude-exec.js +79 -0
  487. package/dist/harness/claude/claude-exec.js.map +1 -0
  488. package/dist/harness/claude/claude-stream.d.ts +31 -0
  489. package/dist/harness/claude/claude-stream.d.ts.map +1 -0
  490. package/dist/harness/claude/claude-stream.js +150 -0
  491. package/dist/harness/claude/claude-stream.js.map +1 -0
  492. package/dist/harness/claude/claude-tools.d.ts +5 -0
  493. package/dist/harness/claude/claude-tools.d.ts.map +1 -0
  494. package/dist/harness/claude/claude-tools.js +30 -0
  495. package/dist/harness/claude/claude-tools.js.map +1 -0
  496. package/dist/harness/index.d.ts +1 -0
  497. package/dist/harness/index.d.ts.map +1 -1
  498. package/dist/harness/index.js +3 -0
  499. package/dist/harness/index.js.map +1 -1
  500. package/dist/harness/opencode/opencode-session.d.ts +42 -0
  501. package/dist/harness/opencode/opencode-session.d.ts.map +1 -0
  502. package/dist/harness/opencode/opencode-session.js +123 -0
  503. package/dist/harness/opencode/opencode-session.js.map +1 -0
  504. package/dist/harness/opencode/opencode.d.ts +2 -1
  505. package/dist/harness/opencode/opencode.d.ts.map +1 -1
  506. package/dist/harness/opencode/opencode.js +52 -28
  507. package/dist/harness/opencode/opencode.js.map +1 -1
  508. package/dist/harness/prompt.js +1 -1
  509. package/dist/harness/prompt.js.map +1 -1
  510. package/dist/harness/types.d.ts +112 -1
  511. package/dist/harness/types.d.ts.map +1 -1
  512. package/dist/harness/types.js.map +1 -1
  513. package/dist/index.d.ts +3 -1
  514. package/dist/index.d.ts.map +1 -1
  515. package/dist/index.js +1 -0
  516. package/dist/index.js.map +1 -1
  517. package/dist/testing/index.d.ts +3 -0
  518. package/dist/testing/index.d.ts.map +1 -0
  519. package/dist/testing/index.js +2 -0
  520. package/dist/testing/index.js.map +1 -0
  521. package/dist/testing/scenario.d.ts +29 -0
  522. package/dist/testing/scenario.d.ts.map +1 -0
  523. package/dist/testing/scenario.js +157 -0
  524. package/dist/testing/scenario.js.map +1 -0
  525. package/dist/watcher/archiver.d.ts +2 -1
  526. package/dist/watcher/archiver.d.ts.map +1 -1
  527. package/dist/watcher/archiver.js +27 -2
  528. package/dist/watcher/archiver.js.map +1 -1
  529. package/dist/watcher/auto-recertify.d.ts +27 -0
  530. package/dist/watcher/auto-recertify.d.ts.map +1 -0
  531. package/dist/watcher/auto-recertify.js +113 -0
  532. package/dist/watcher/auto-recertify.js.map +1 -0
  533. package/dist/watcher/auto-retry.d.ts +1 -1
  534. package/dist/watcher/auto-retry.d.ts.map +1 -1
  535. package/dist/watcher/auto-retry.js +3 -11
  536. package/dist/watcher/auto-retry.js.map +1 -1
  537. package/dist/watcher/baseline-key.d.ts +17 -0
  538. package/dist/watcher/baseline-key.d.ts.map +1 -0
  539. package/dist/watcher/baseline-key.js +31 -0
  540. package/dist/watcher/baseline-key.js.map +1 -0
  541. package/dist/watcher/baseline.d.ts +32 -0
  542. package/dist/watcher/baseline.d.ts.map +1 -0
  543. package/dist/watcher/baseline.js +166 -0
  544. package/dist/watcher/baseline.js.map +1 -0
  545. package/dist/watcher/blocked.d.ts +12 -0
  546. package/dist/watcher/blocked.d.ts.map +1 -0
  547. package/dist/watcher/blocked.js +24 -0
  548. package/dist/watcher/blocked.js.map +1 -0
  549. package/dist/watcher/dependencies.d.ts +28 -0
  550. package/dist/watcher/dependencies.d.ts.map +1 -0
  551. package/dist/watcher/dependencies.js +152 -0
  552. package/dist/watcher/dependencies.js.map +1 -0
  553. package/dist/watcher/done-metadata.d.ts +4 -0
  554. package/dist/watcher/done-metadata.d.ts.map +1 -0
  555. package/dist/watcher/done-metadata.js +20 -0
  556. package/dist/watcher/done-metadata.js.map +1 -0
  557. package/dist/watcher/failure-reason.d.ts +1 -1
  558. package/dist/watcher/failure-reason.d.ts.map +1 -1
  559. package/dist/watcher/focused-verify.d.ts +17 -0
  560. package/dist/watcher/focused-verify.d.ts.map +1 -0
  561. package/dist/watcher/focused-verify.js +54 -0
  562. package/dist/watcher/focused-verify.js.map +1 -0
  563. package/dist/watcher/git-guard.d.ts +24 -0
  564. package/dist/watcher/git-guard.d.ts.map +1 -0
  565. package/dist/watcher/git-guard.js +95 -0
  566. package/dist/watcher/git-guard.js.map +1 -0
  567. package/dist/watcher/instructions-drift.d.ts +21 -0
  568. package/dist/watcher/instructions-drift.d.ts.map +1 -0
  569. package/dist/watcher/instructions-drift.js +115 -0
  570. package/dist/watcher/instructions-drift.js.map +1 -0
  571. package/dist/watcher/loop.d.ts.map +1 -1
  572. package/dist/watcher/loop.js +36 -50
  573. package/dist/watcher/loop.js.map +1 -1
  574. package/dist/watcher/measures.d.ts.map +1 -1
  575. package/dist/watcher/measures.js +22 -39
  576. package/dist/watcher/measures.js.map +1 -1
  577. package/dist/watcher/mutation-check.d.ts +42 -0
  578. package/dist/watcher/mutation-check.d.ts.map +1 -0
  579. package/dist/watcher/mutation-check.js +147 -0
  580. package/dist/watcher/mutation-check.js.map +1 -0
  581. package/dist/watcher/regression.d.ts +10 -5
  582. package/dist/watcher/regression.d.ts.map +1 -1
  583. package/dist/watcher/regression.js +29 -22
  584. package/dist/watcher/regression.js.map +1 -1
  585. package/dist/watcher/runner.d.ts.map +1 -1
  586. package/dist/watcher/runner.js +12 -14
  587. package/dist/watcher/runner.js.map +1 -1
  588. package/dist/watcher/spawn.d.ts.map +1 -1
  589. package/dist/watcher/spawn.js +5 -0
  590. package/dist/watcher/spawn.js.map +1 -1
  591. package/dist/watcher/task-verify.d.ts +7 -2
  592. package/dist/watcher/task-verify.d.ts.map +1 -1
  593. package/dist/watcher/task-verify.js +33 -8
  594. package/dist/watcher/task-verify.js.map +1 -1
  595. package/dist/watcher/verify.d.ts +1 -5
  596. package/dist/watcher/verify.d.ts.map +1 -1
  597. package/dist/watcher/verify.js +2 -6
  598. package/dist/watcher/verify.js.map +1 -1
  599. package/package.json +5 -1
  600. package/templates/PLANNER.md +35 -9
  601. package/templates/openspec/config.yaml +1 -1
  602. package/templates/openspec/schemas/osq/schema.yaml +4 -2
  603. package/templates/openspec/schemas/osq/templates/proposal.md +9 -2
  604. package/templates/proposal.md +9 -2
  605. package/ui/dist/assets/{index-CZYeQ8la.js → index-D39uYbbL.js} +1 -1
  606. package/ui/dist/index.html +1 -1
@@ -2,12 +2,15 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { DEFAULT_CONFIG } from '../foundation/config.js';
4
4
  import { appendObservedSessions, findPlanningSessions, resolveChangeCreationTime, } from '../report/planning-observed.js';
5
- import { hashBriefBytes, resolveOsqPackageVersion } from '../report/planning.js';
6
- import { buildManifest, writeManifest } from '../run/manifest.js';
7
- import { getChangesDir } from '../status/layout.js';
8
- import { buildApprovalDigest, summarizeApprovalFlags, } from './digest.js';
5
+ import { findUnpricedPlanningModels } from '../report/planning-price-gaps.js';
6
+ import { resolveOsqPackageVersion } from '../report/planning.js';
7
+ import { findChange } from '../status/change-locations.js';
8
+ import { selectVcs } from '../vcs/select.js';
9
+ import { confirmApproval, readBriefHash, toIso, writeApprovalSeal, } from './approve-worktree-shared.js';
10
+ import { approveIntoWorktree } from './approve-worktree.js';
9
11
  import { hashChangeFolder } from './hasher.js';
10
12
  import { lintChangeFolder } from './linter.js';
13
+ export { ApprovalDeclinedError } from './approve-worktree-shared.js';
11
14
  export async function findSpecFolder(specsDir, idOrPrefix) {
12
15
  let entries = [];
13
16
  try {
@@ -33,46 +36,10 @@ export async function findSpecFolder(specsDir, idOrPrefix) {
33
36
  }
34
37
  throw new Error(`Spec "${idOrPrefix}" not found in ${specsDir}`);
35
38
  }
36
- /** Thrown when an approver declined a flagged approval; nothing is written. */
37
- export class ApprovalDeclinedError extends Error {
38
- constructor(flags) {
39
- super(`Approval declined: ${summarizeApprovalFlags(flags)}`);
40
- this.name = 'ApprovalDeclinedError';
41
- }
42
- }
43
- function toIso(value) {
44
- if (value instanceof Date) {
45
- return Number.isFinite(value.getTime()) ? value.toISOString() : null;
46
- }
47
- if (typeof value === 'string') {
48
- return Number.isFinite(Date.parse(value)) ? value : null;
49
- }
50
- return null;
51
- }
52
- async function readBriefHash(folderPath) {
53
- const bytes = await fs.readFile(path.join(folderPath, 'brief.md')).catch(() => null);
54
- return hashBriefBytes(bytes ?? '');
55
- }
56
- export async function approveSpec(projectRoot, specIdOrPrefix, config, options = {}) {
57
- const specsDir = getChangesDir(config.paths.openspecRoot, projectRoot);
58
- const folderPath = await findSpecFolder(specsDir, specIdOrPrefix);
59
- const folderName = path.basename(folderPath);
60
- const specId = folderName.match(/^(\d+)/)?.[1] || folderName;
61
- const lintResult = await lintChangeFolder(projectRoot, folderPath, config);
62
- if (!lintResult.valid) {
63
- throw new Error(`Lint failed for spec "${folderName}":\n - ${lintResult.errors.join('\n - ')}`);
64
- }
65
- // Build the digest after lint and before any observation write, then let the
66
- // optional review port decide whether a flagged approval may proceed.
67
- const digest = await buildApprovalDigest(projectRoot, folderPath, config);
68
- let mode = 'shown';
69
- if (options.review) {
70
- const review = await options.review(digest);
71
- if (review === 'declined') {
72
- throw new ApprovalDeclinedError(digest.flags);
73
- }
74
- mode = review === 'confirmed' ? 'confirmed' : 'shown';
75
- }
39
+ /** The pre-worktree path: seal and observe inside the checkout's folder. */
40
+ async function approveInPlace(projectRoot, input) {
41
+ const { specId, folderName, folderPath, specsDir, config, options, warnings } = input;
42
+ const { digest, mode } = await confirmApproval(projectRoot, folderPath, config, options);
76
43
  // Discover local planning sessions after lint so a failed change is never
77
44
  // recorded, then append observed pairs before the manifest is built.
78
45
  const observations = await findPlanningSessions(folderPath, {
@@ -86,26 +53,62 @@ export async function approveSpec(projectRoot, specIdOrPrefix, config, options =
86
53
  briefHash: await readBriefHash(folderPath),
87
54
  osqVersion: await resolveOsqPackageVersion(),
88
55
  });
56
+ // Price gaps are read after observation so a session found at approval is
57
+ // named too. Approval itself is unaffected.
58
+ const missingPrices = await findUnpricedPlanningModels([folderPath], config.planning?.prices);
89
59
  const hash = await hashChangeFolder(folderPath);
90
60
  // Approval only refreshes the seal. It never retires failure markers: that is
91
61
  // the exclusive job of an explicit `osq retry`.
92
- const runDir = path.join(folderPath, '.run');
93
- await fs.mkdir(runDir, { recursive: true });
94
- const approvedPath = path.join(runDir, 'approved');
95
- await fs.writeFile(approvedPath, `${hash}\n`, 'utf8');
96
- const manifest = await buildManifest(projectRoot, folderPath, config, {
97
- ids: digest.flags.map((flag) => flag.id),
98
- mode,
99
- });
100
- await writeManifest(runDir, manifest);
62
+ await writeApprovalSeal(projectRoot, folderPath, config, digest, mode, hash);
101
63
  return {
102
64
  specId,
103
65
  folderName,
104
66
  folderPath,
105
67
  hash,
106
- warnings: lintResult.warnings,
68
+ warnings,
107
69
  planningMatches: observations.length,
70
+ missingPrices,
108
71
  digest,
109
72
  };
110
73
  }
74
+ /**
75
+ * Approve one change. Lint always runs in the checkout. With `vcs.enabled` and
76
+ * git selected, the seal and commit go to a linked worktree and the checkout
77
+ * is left untouched; otherwise approval writes in place as before.
78
+ */
79
+ export async function approveSpec(projectRoot, specIdOrPrefix, config, options = {}) {
80
+ const change = await findChange(projectRoot, config, specIdOrPrefix);
81
+ const folderPath = change.folderPath;
82
+ const specsDir = change.tree.changesDir;
83
+ const folderName = path.basename(folderPath);
84
+ const specId = folderName.match(/^(\d+)/)?.[1] || folderName;
85
+ const lintResult = await lintChangeFolder(projectRoot, folderPath, config);
86
+ if (!lintResult.valid) {
87
+ throw new Error(`Lint failed for spec "${folderName}":\n - ${lintResult.errors.join('\n - ')}`);
88
+ }
89
+ if (config.vcs?.enabled === true) {
90
+ const vcs = await selectVcs(projectRoot, config);
91
+ if (vcs.kind === 'git') {
92
+ return approveIntoWorktree(projectRoot, {
93
+ specId,
94
+ folderName,
95
+ folderPath,
96
+ specsDir,
97
+ config,
98
+ options,
99
+ vcs,
100
+ warnings: lintResult.warnings,
101
+ });
102
+ }
103
+ }
104
+ return approveInPlace(projectRoot, {
105
+ specId,
106
+ folderName,
107
+ folderPath,
108
+ specsDir,
109
+ config,
110
+ options,
111
+ warnings: lintResult.warnings,
112
+ });
113
+ }
111
114
  //# sourceMappingURL=approve.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../../src/core/spec/approve.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../../src/core/spec/approve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAkB,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAEL,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAEL,eAAe,EACf,aAAa,EACb,KAAK,EACL,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAM/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,UAAkB;IACvE,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAE3E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IACE,KAAK,KAAK,OAAO;YACjB,KAAK,KAAK,MAAM;YAChB,KAAK,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,CAAC;YAC/B,KAAK,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,EAC9B,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,SAAS,UAAU,kBAAkB,QAAQ,EAAE,CAAC,CAAC;AACnE,CAAC;AAyCD,4EAA4E;AAC5E,KAAK,UAAU,cAAc,CAAC,WAAmB,EAAE,KAAsB;IACvE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACtF,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAEzF,0EAA0E;IAC1E,qEAAqE;IACrE,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAAC,UAAU,EAAE;QAC1D,SAAS,EAAE,MAAM,yBAAyB,CAAC,UAAU,CAAC;QACtD,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC1D,UAAU,EAAE,QAAQ;QACpB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,cAAc,CAAC,QAAQ;QACpD,OAAO,EAAE,OAAO,CAAC,eAAe,IAAI,EAAE;KACvC,CAAC,CAAC;IACH,MAAM,sBAAsB,CAAC,UAAU,EAAE,YAAY,EAAE;QACrD,SAAS,EAAE,MAAM,aAAa,CAAC,UAAU,CAAC;QAC1C,UAAU,EAAE,MAAM,wBAAwB,EAAE;KAC7C,CAAC,CAAC;IAEH,0EAA0E;IAC1E,4CAA4C;IAC5C,MAAM,aAAa,GAAG,MAAM,0BAA0B,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAEhD,8EAA8E;IAC9E,gDAAgD;IAChD,MAAM,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAE7E,OAAO;QACL,MAAM;QACN,UAAU;QACV,UAAU;QACV,IAAI;QACJ,QAAQ;QACR,eAAe,EAAE,YAAY,CAAC,MAAM;QACpC,aAAa;QACb,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,WAAmB,EACnB,cAAsB,EACtB,MAAiB,EACjB,UAA0B,EAAE;IAE5B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;IAE7D,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC3E,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,yBAAyB,UAAU,WAAW,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACvB,OAAO,mBAAmB,CAAC,WAAW,EAAE;gBACtC,MAAM;gBACN,UAAU;gBACV,UAAU;gBACV,QAAQ;gBACR,MAAM;gBACN,OAAO;gBACP,GAAG;gBACH,QAAQ,EAAE,UAAU,CAAC,QAAQ;aAC9B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC,WAAW,EAAE;QACjC,MAAM;QACN,UAAU;QACV,UAAU;QACV,QAAQ;QACR,MAAM;QACN,OAAO;QACP,QAAQ,EAAE,UAAU,CAAC,QAAQ;KAC9B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type LintFinding } from './lint-findings.js';
2
+ /**
3
+ * The capability half of impact lint: a scoped file that imports code owned by
4
+ * a capability the proposal neither reads nor writes, and a resolved scope path
5
+ * owned by no capability with a delta. Both never affect validity.
6
+ */
7
+ /** One living capability's declared Code ownership globs. */
8
+ export interface CapabilityOwnership {
9
+ readonly capability: string;
10
+ readonly globs: readonly string[];
11
+ }
12
+ /** Read every living spec's Code ownership globs, in capability name order. */
13
+ export declare function readCapabilityOwnership(projectRoot: string, openspecRoot: string): Promise<CapabilityOwnership[]>;
14
+ /** Capabilities whose Code ownership globs cover one path, sorted by name. */
15
+ export declare function ownerCapabilities(ownerships: readonly CapabilityOwnership[], relativePath: string): string[];
16
+ /** One task's resolved write surface for the write-without-delta check. */
17
+ export interface CapabilityWriteTask {
18
+ readonly taskNumber: string;
19
+ readonly taskPath: string;
20
+ readonly existingPaths: readonly string[];
21
+ }
22
+ /**
23
+ * Warn once per resolved scope path owned by capabilities none of which has a
24
+ * delta in the change. Paths no living spec owns are left alone.
25
+ */
26
+ export declare function writeWithoutDeltaFindings(tasks: readonly CapabilityWriteTask[], ownerships: readonly CapabilityOwnership[], deltaCapabilities: ReadonlySet<string>): LintFinding[];
27
+ /** The direct imports a capability read check reads, plus what counts as declared. */
28
+ export interface CapabilityReadInput {
29
+ readonly proposalPath: string;
30
+ readonly scopedFiles: readonly string[];
31
+ readonly importsOf: (file: string) => readonly string[];
32
+ readonly filesInScope: ReadonlySet<string>;
33
+ readonly ownerships: readonly CapabilityOwnership[];
34
+ /** Capability names in `features.reads` or with a delta in the change. */
35
+ readonly declared: ReadonlySet<string>;
36
+ }
37
+ /**
38
+ * Warn once per capability owning code a scoped file imports directly, when no
39
+ * owner of the imported file is read or has a delta and the file is out of every
40
+ * task's scope.
41
+ */
42
+ export declare function undeclaredReadFindings(input: CapabilityReadInput): LintFinding[];
43
+ //# sourceMappingURL=capability-impact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-impact.d.ts","sourceRoot":"","sources":["../../../src/core/spec/capability-impact.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAGnE;;;;GAIG;AAEH,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,+EAA+E;AAC/E,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAwBhC;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,SAAS,mBAAmB,EAAE,EAC1C,YAAY,EAAE,MAAM,GACnB,MAAM,EAAE,CAKV;AAED,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,UAAU,EAAE,SAAS,mBAAmB,EAAE,EAC1C,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,GACrC,WAAW,EAAE,CAmBf;AAED,sFAAsF;AACtF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,CAAC;IACxD,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACpD,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,GAAG,WAAW,EAAE,CA2BhF"}
@@ -0,0 +1,85 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { scopeCoversPath } from '../run/scope.js';
4
+ import { getSpecsDir } from '../status/layout.js';
5
+ import { makeFinding } from './lint-findings.js';
6
+ import { parseCodeOwnership } from './parser.js';
7
+ /** Read every living spec's Code ownership globs, in capability name order. */
8
+ export async function readCapabilityOwnership(projectRoot, openspecRoot) {
9
+ const specsDir = getSpecsDir(openspecRoot, projectRoot);
10
+ let entries;
11
+ try {
12
+ entries = await fs.readdir(specsDir, { withFileTypes: true });
13
+ }
14
+ catch {
15
+ return [];
16
+ }
17
+ const ownerships = [];
18
+ const directories = entries
19
+ .filter((entry) => entry.isDirectory())
20
+ .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
21
+ for (const entry of directories) {
22
+ const content = await fs
23
+ .readFile(path.join(specsDir, entry.name, 'spec.md'), 'utf8')
24
+ .catch(() => null);
25
+ if (content === null)
26
+ continue;
27
+ const globs = parseCodeOwnership(content);
28
+ if (globs.length > 0)
29
+ ownerships.push({ capability: entry.name, globs });
30
+ }
31
+ return ownerships;
32
+ }
33
+ /** Capabilities whose Code ownership globs cover one path, sorted by name. */
34
+ export function ownerCapabilities(ownerships, relativePath) {
35
+ return ownerships
36
+ .filter((entry) => scopeCoversPath(entry.globs, relativePath))
37
+ .map((entry) => entry.capability)
38
+ .sort();
39
+ }
40
+ /**
41
+ * Warn once per resolved scope path owned by capabilities none of which has a
42
+ * delta in the change. Paths no living spec owns are left alone.
43
+ */
44
+ export function writeWithoutDeltaFindings(tasks, ownerships, deltaCapabilities) {
45
+ const findings = [];
46
+ for (const task of tasks) {
47
+ for (const scopePath of task.existingPaths) {
48
+ const owners = ownerCapabilities(ownerships, scopePath);
49
+ if (owners.length === 0)
50
+ continue;
51
+ if (owners.some((owner) => deltaCapabilities.has(owner)))
52
+ continue;
53
+ findings.push(makeFinding('warning', { file: task.taskPath }, `${scopePath} is owned by ${owners.join(', ')}, which has no delta in this change. Add a delta or move the file out of scope`));
54
+ }
55
+ }
56
+ return findings;
57
+ }
58
+ /**
59
+ * Warn once per capability owning code a scoped file imports directly, when no
60
+ * owner of the imported file is read or has a delta and the file is out of every
61
+ * task's scope.
62
+ */
63
+ export function undeclaredReadFindings(input) {
64
+ const importersByCapability = new Map();
65
+ for (const scoped of input.scopedFiles) {
66
+ for (const imported of input.importsOf(scoped)) {
67
+ if (input.filesInScope.has(imported))
68
+ continue;
69
+ const owners = ownerCapabilities(input.ownerships, imported);
70
+ if (owners.length === 0)
71
+ continue;
72
+ if (owners.some((owner) => input.declared.has(owner)))
73
+ continue;
74
+ for (const owner of owners) {
75
+ const importers = importersByCapability.get(owner) ?? new Set();
76
+ importers.add(scoped);
77
+ importersByCapability.set(owner, importers);
78
+ }
79
+ }
80
+ }
81
+ return [...importersByCapability.entries()]
82
+ .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
83
+ .map(([capability, importers]) => makeFinding('warning', { file: input.proposalPath }, `Scoped files import code owned by the ${capability} capability: ${[...importers].sort().join(', ')}. Add ${capability} to features.reads`));
84
+ }
85
+ //# sourceMappingURL=capability-impact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-impact.js","sourceRoot":"","sources":["../../../src/core/spec/capability-impact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { OsqConfig } from '../foundation/config.js';
2
+ import { type LintFinding } from './lint-findings.js';
3
+ export interface DecisionsLintInput {
4
+ readonly projectRoot: string;
5
+ readonly folderPath: string;
6
+ /** Repository-relative `proposal.md`; the change document's own findings. */
7
+ readonly proposalPath: string;
8
+ /** The proposal body with frontmatter stripped. */
9
+ readonly proposalBody: string;
10
+ readonly config: OsqConfig;
11
+ }
12
+ /**
13
+ * Checks a proposal's Decisions section and, when the project has ADRs, the
14
+ * AGENTS.md project rules block. Returns the change's own findings; a project
15
+ * whose decisions folder holds no ADR with osq frontmatter returns none.
16
+ */
17
+ export declare function collectDecisionsFindings(input: DecisionsLintInput): Promise<LintFinding[]>;
18
+ //# sourceMappingURL=decisions-lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decisions-lint.d.ts","sourceRoot":"","sources":["../../../src/core/spec/decisions-lint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAiBnE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;CAC5B;AAqHD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA2BhG"}
@@ -0,0 +1,127 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { readDecisions, sameAdrNumber } from '../foundation/decisions.js';
4
+ import { checkProjectRules } from '../foundation/rules-block.js';
5
+ import { makeFinding } from './lint-findings.js';
6
+ /**
7
+ * Decisions lint: the proposal's `## Decisions` section and the AGENTS.md
8
+ * project rules block, checked only when the project has at least one ADR with
9
+ * osq frontmatter. A project without ADRs returns no findings.
10
+ */
11
+ /** HTML comments are structural scaffolding, not declared decision text. */
12
+ const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
13
+ /** An `ADR <n>` mention anywhere in the section; a departure line names its ADR. */
14
+ const ADR_MENTION_REGEX = /\bADR\s+(\d+)/g;
15
+ const MISSING_SECTION_ERROR = 'proposal.md needs a ## Decisions section: name each accepted ADR that governs a capability this change writes, or write None';
16
+ /**
17
+ * Reads a proposal body's `## <heading>` section content. The heading must
18
+ * occupy its own line; a mention inside prose does not count. Returns `null`
19
+ * when the section is absent.
20
+ */
21
+ function readSection(body, heading) {
22
+ const match = new RegExp(`^##\\s+${heading}\\s*$`, 'm').exec(body);
23
+ if (!match) {
24
+ return null;
25
+ }
26
+ const rest = body.slice(match.index + match[0].length);
27
+ const boundary = rest.search(/\n##(?!#)\s/);
28
+ return boundary === -1 ? rest : rest.slice(0, boundary);
29
+ }
30
+ /** True when a section holds only HTML comments and whitespace. */
31
+ function sectionIsBlank(section) {
32
+ return section.replace(HTML_COMMENT_REGEX, '').trim().length === 0;
33
+ }
34
+ /** True when `target` exists as a regular file. */
35
+ async function fileExists(target) {
36
+ return fs
37
+ .stat(target)
38
+ .then((stat) => stat.isFile())
39
+ .catch(() => false);
40
+ }
41
+ /** Capability names whose directory under the change's `specs/` holds `spec.md`. */
42
+ async function readWrittenCapabilities(folderPath) {
43
+ let entries;
44
+ try {
45
+ entries = await fs.readdir(path.join(folderPath, 'specs'), { withFileTypes: true });
46
+ }
47
+ catch {
48
+ return [];
49
+ }
50
+ const capabilities = [];
51
+ for (const entry of entries) {
52
+ if (!entry.isDirectory()) {
53
+ continue;
54
+ }
55
+ if (await fileExists(path.join(folderPath, 'specs', entry.name, 'spec.md'))) {
56
+ capabilities.push(entry.name);
57
+ }
58
+ }
59
+ return capabilities.sort();
60
+ }
61
+ /** The distinct ADR numbers named anywhere in a Decisions section, in order. */
62
+ function mentionedAdrNumbers(section) {
63
+ const numbers = [];
64
+ for (const match of section.matchAll(ADR_MENTION_REGEX)) {
65
+ if (!numbers.some((number) => sameAdrNumber(number, match[1]))) {
66
+ numbers.push(match[1]);
67
+ }
68
+ }
69
+ return numbers;
70
+ }
71
+ /** One error per governing capability ADR the section leaves unnamed. */
72
+ function unnamedAdrFindings(section, adrs, written, proposalPath) {
73
+ const mentioned = mentionedAdrNumbers(section);
74
+ const findings = [];
75
+ for (const adr of adrs) {
76
+ const applies = adr.appliesTo;
77
+ if (adr.status !== 'accepted' || applies === null || applies === 'all') {
78
+ continue;
79
+ }
80
+ const capability = written.find((name) => applies.includes(name));
81
+ if (capability === undefined) {
82
+ continue;
83
+ }
84
+ if (mentioned.some((number) => sameAdrNumber(number, adr.number))) {
85
+ continue;
86
+ }
87
+ findings.push(makeFinding('error', { file: proposalPath, section: 'Decisions' }, `proposal.md ## Decisions does not name ADR ${adr.number}, which applies to ${capability}`));
88
+ }
89
+ return findings;
90
+ }
91
+ /** One warning per named ADR number that doesn't exist or isn't accepted. */
92
+ function unknownAdrFindings(section, adrs, proposalPath) {
93
+ const findings = [];
94
+ for (const number of mentionedAdrNumbers(section)) {
95
+ const adr = adrs.find((entry) => sameAdrNumber(entry.number, number));
96
+ if (adr !== undefined && adr.status === 'accepted') {
97
+ continue;
98
+ }
99
+ findings.push(makeFinding('warning', { file: proposalPath, section: 'Decisions' }, `proposal.md ## Decisions names ADR ${number}, which does not exist or is not accepted`));
100
+ }
101
+ return findings;
102
+ }
103
+ /**
104
+ * Checks a proposal's Decisions section and, when the project has ADRs, the
105
+ * AGENTS.md project rules block. Returns the change's own findings; a project
106
+ * whose decisions folder holds no ADR with osq frontmatter returns none.
107
+ */
108
+ export async function collectDecisionsFindings(input) {
109
+ const records = await readDecisions(input.projectRoot, input.config);
110
+ if (records.adrs.length === 0) {
111
+ return [];
112
+ }
113
+ const findings = [];
114
+ for (const message of await checkProjectRules(input.projectRoot, input.config)) {
115
+ findings.push(makeFinding('error', { file: 'AGENTS.md' }, message));
116
+ }
117
+ const section = readSection(input.proposalBody, 'Decisions');
118
+ if (section === null || sectionIsBlank(section)) {
119
+ findings.push(makeFinding('error', { file: input.proposalPath, section: 'Decisions' }, MISSING_SECTION_ERROR));
120
+ return findings;
121
+ }
122
+ const written = await readWrittenCapabilities(input.folderPath);
123
+ findings.push(...unnamedAdrFindings(section, records.adrs, written, input.proposalPath));
124
+ findings.push(...unknownAdrFindings(section, records.adrs, input.proposalPath));
125
+ return findings;
126
+ }
127
+ //# sourceMappingURL=decisions-lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decisions-lint.js","sourceRoot":"","sources":["../../../src/core/spec/decisions-lint.ts"],"names":[],"mappings":"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"}
@@ -14,10 +14,16 @@
14
14
  * name that already exists with different content, a bare RENAMED entry, and an
15
15
  * unmatched RENAMED, MODIFIED, or REMOVED target.
16
16
  */
17
+ /** One THEN or AND assertion, with the table directly under it when present. */
18
+ export interface ScenarioOutcome {
19
+ readonly text: string;
20
+ readonly rows?: readonly Record<string, string>[];
21
+ }
17
22
  export interface DeltaScenario {
18
23
  readonly name: string;
19
24
  readonly when: string[];
20
25
  readonly then: string[];
26
+ readonly outcomes: readonly ScenarioOutcome[];
21
27
  readonly raw: string;
22
28
  }
23
29
  export interface DeltaRequirement {
@@ -1 +1 @@
1
- {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../../src/core/spec/delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,aAAa,EAAE,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,cAAc,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAC3C;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAwBD,mFAAmF;AACnF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AA4DD,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAE9D;AAWD,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAuBxD;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBzE;AAuPD,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAqBvD;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAUnE;AAED,qEAAqE;AACrE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAUpE;AAyND;;;GAGG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,WAAW,GACjB,MAAM,CAgCR"}
1
+ {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../../src/core/spec/delta.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,11 @@ const RENAME_FROM_REGEX = /^\s*[-*+]?\s*FROM:\s*`?###\s*Requirement:\s*(.+?)`?\s
22
22
  const RENAME_TO_REGEX = /^\s*[-*+]?\s*TO:\s*`?###\s*Requirement:\s*(.+?)`?\s*$/;
23
23
  const ANY_RENAME_REGEX = /^\s*[-*+]?\s*(FROM|TO):\s*(.*)$/i;
24
24
  const REMOVED_BULLET_REGEX = /^\s*[-*+]\s*`?###\s*Requirement:\s*(.+?)`?\s*$/;
25
+ const WHEN_BULLET_REGEX = /^-[ \t]+\*\*WHEN\*\*[ \t]*(.*)$/;
26
+ const THEN_BULLET_REGEX = /^-[ \t]+\*\*THEN\*\*[ \t]*(.*)$/;
27
+ const AND_BULLET_REGEX = /^-[ \t]+\*\*AND\*\*[ \t]*(.*)$/;
28
+ const TABLE_ROW_REGEX = /^\s*\|.*\|\s*$/;
29
+ const TABLE_SEPARATOR_CELL_REGEX = /^:?-+:?$/;
25
30
  const PURPOSE_PLACEHOLDER_PREFIX = 'TBD - created by archiving change ';
26
31
  const PURPOSE_PLACEHOLDER_SUFFIX = '. Update Purpose after archive.';
27
32
  export class DeltaMergeError extends Error {
@@ -111,18 +116,81 @@ export function parseScenario(raw) {
111
116
  const name = scenarioNameAt(lines[0]);
112
117
  const when = [];
113
118
  const then = [];
114
- for (const line of lines.slice(1)) {
115
- const whenMatch = line.match(/^-[ \t]+\*\*WHEN\*\*[ \t]*(.*)$/);
119
+ const outcomes = [];
120
+ let thenSeen = false;
121
+ for (let index = 1; index < lines.length; index++) {
122
+ const line = lines[index];
123
+ const whenMatch = line.match(WHEN_BULLET_REGEX);
116
124
  if (whenMatch) {
117
125
  when.push(whenMatch[1].trim());
126
+ thenSeen = false;
118
127
  continue;
119
128
  }
120
- const thenMatch = line.match(/^-[ \t]+\*\*THEN\*\*[ \t]*(.*)$/);
129
+ const thenMatch = line.match(THEN_BULLET_REGEX);
121
130
  if (thenMatch) {
122
- then.push(thenMatch[1].trim());
131
+ const text = thenMatch[1].trim();
132
+ then.push(text);
133
+ outcomes.push(outcomeWithTable(text, lines, index + 1));
134
+ thenSeen = true;
135
+ continue;
136
+ }
137
+ const andMatch = line.match(AND_BULLET_REGEX);
138
+ if (andMatch && thenSeen) {
139
+ outcomes.push(outcomeWithTable(andMatch[1].trim(), lines, index + 1));
140
+ }
141
+ }
142
+ return { name, when, then, outcomes, raw: normalizeLineEndings(raw).trimEnd() };
143
+ }
144
+ /** An outcome line paired with the table directly below it, if any. */
145
+ function outcomeWithTable(text, lines, start) {
146
+ const rows = readTableRows(lines, start);
147
+ return rows === undefined ? { text } : { text, rows };
148
+ }
149
+ /** Split one Markdown table row into its trimmed cells. */
150
+ function splitTableRow(line) {
151
+ return line
152
+ .trim()
153
+ .replace(/^\|/, '')
154
+ .replace(/\|$/, '')
155
+ .split('|')
156
+ .map((cell) => cell.trim());
157
+ }
158
+ /** True when a table row is the dashes-and-colons alignment row. */
159
+ function isTableSeparator(line) {
160
+ const cells = splitTableRow(line);
161
+ return cells.length > 0 && cells.every((cell) => TABLE_SEPARATOR_CELL_REGEX.test(cell));
162
+ }
163
+ /**
164
+ * Read the Markdown table directly under an outcome line. Blank lines may sit
165
+ * between the outcome and the table, and the table may be indented. The first
166
+ * row names the columns, the alignment row is left out, and each later row is
167
+ * keyed by the header cells, a missing cell reading as the empty string.
168
+ * Returns undefined when no table follows the outcome.
169
+ */
170
+ function readTableRows(lines, start) {
171
+ let index = start;
172
+ while (index < lines.length && lines[index].trim() === '') {
173
+ index++;
174
+ }
175
+ if (index >= lines.length || !TABLE_ROW_REGEX.test(lines[index])) {
176
+ return undefined;
177
+ }
178
+ const header = splitTableRow(lines[index]);
179
+ index++;
180
+ if (index < lines.length && isTableSeparator(lines[index])) {
181
+ index++;
182
+ }
183
+ const rows = [];
184
+ while (index < lines.length && TABLE_ROW_REGEX.test(lines[index])) {
185
+ const cells = splitTableRow(lines[index]);
186
+ const row = {};
187
+ for (let column = 0; column < header.length; column++) {
188
+ row[header[column]] = cells[column] ?? '';
123
189
  }
190
+ rows.push(row);
191
+ index++;
124
192
  }
125
- return { name, when, then, raw: normalizeLineEndings(raw).trimEnd() };
193
+ return rows;
126
194
  }
127
195
  /** The body of a `## Purpose` section, or undefined when it is absent or empty. */
128
196
  export function extractPurposeSection(content) {