@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
@@ -1,16 +1,26 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { DEFAULT_CONFIG } from '../foundation/config.js';
4
+ import { readManifestApprovedAt } from '../run/manifest-approval.js';
4
5
  import { parseFrontmatter, parseTaskMd } from '../spec/parser.js';
5
- import { getArchiveDir, getChangesDir, getRejectedDir } from '../status/layout.js';
6
+ import { changeTrees, listChanges } from '../status/change-locations.js';
6
7
  import { readQueueReport } from '../status/queue-report.js';
7
8
  import { compareNumericPrefix, deriveSpecState } from '../status/state.js';
8
9
  import { collectApprovalFlagOutcomes, formatApprovalFlagOutcomes, } from './approval-flags.js';
10
+ import { readBriefToApprovalSeconds } from './brief-to-approval.js';
9
11
  import { buildPlanningComparison, computePlanningByChange, } from './planning-economics.js';
10
12
  import { readPlanningSessions } from './planning.js';
13
+ import { collectDisclosures, formatDisclosures, } from './record-disclosures.js';
14
+ import { collectCostBySource, formatPlanningCostBySource, } from './record-estimates.js';
15
+ import { collectRework, formatRework } from './record-rework.js';
16
+ import { collectVerificationCounts, formatVerificationCounts, } from './record-verification.js';
17
+ import { collectDependencies, formatDependencies, } from './report-dependencies.js';
11
18
  import { asData, eventTimestampMs, observeAttempts, observeTaskStream, parseEventLines, parseTokenEvent, } from './report-events.js';
19
+ import { collectMutationScores, formatMutation, } from './report-mutation.js';
12
20
  import { observePreSpawnEvents } from './report-pre-spawn.js';
13
21
  import { addRetryHistory, emptyRetryHistory, observeRetries, } from './report-retries.js';
22
+ import { collectTraceabilityGaps, formatTraceability, } from './report-traceability.js';
23
+ import { taskScopeSize } from './scope-size.js';
14
24
  export function formatDuration(ms) {
15
25
  if (ms <= 0)
16
26
  return '0s';
@@ -123,7 +133,7 @@ async function readTaskMetadata(folderPath, taskNumber) {
123
133
  * start-to-end pairs and is null when no pair completes.
124
134
  */
125
135
  function deriveMeasuredTask(change, task, events) {
126
- let scopeFiles = null;
136
+ let startScopeFiles = null;
127
137
  let scopeResolver;
128
138
  let pendingStartMs = null;
129
139
  let coveredMs = 0;
@@ -134,11 +144,11 @@ function deriveMeasuredTask(change, task, events) {
134
144
  const data = asData(event);
135
145
  if (data?.phase === 'start') {
136
146
  const rawScopeFiles = data.scopeFiles;
137
- if (scopeFiles === null &&
147
+ if (startScopeFiles === null &&
138
148
  typeof rawScopeFiles === 'number' &&
139
149
  Number.isFinite(rawScopeFiles) &&
140
150
  rawScopeFiles >= 0) {
141
- scopeFiles = rawScopeFiles;
151
+ startScopeFiles = rawScopeFiles;
142
152
  scopeResolver = data.scopeResolver;
143
153
  }
144
154
  pendingStartMs = eventTimestampMs(event);
@@ -152,14 +162,14 @@ function deriveMeasuredTask(change, task, events) {
152
162
  pendingStartMs = null;
153
163
  }
154
164
  }
155
- if (scopeFiles === null)
165
+ if (startScopeFiles === null)
156
166
  return null;
157
167
  const { attempts, firstAttemptPass } = observeAttempts(events);
158
168
  return {
159
169
  change,
160
170
  task,
161
171
  scopeResolver,
162
- scopeFiles,
172
+ scopeFiles: taskScopeSize(events, startScopeFiles),
163
173
  attempts,
164
174
  firstAttemptPass,
165
175
  durationSeconds: hasDuration ? coveredMs / 1000 : null,
@@ -304,45 +314,16 @@ function formatSizeBucketLines(rows) {
304
314
  }
305
315
  return lines;
306
316
  }
307
- /** Parses a `brief.md` frontmatter `date` value into epoch milliseconds. */
308
- function parseBriefDateMs(data) {
309
- const value = data.date;
310
- if (value instanceof Date) {
311
- const ms = value.getTime();
312
- return Number.isFinite(ms) ? ms : null;
313
- }
314
- if (typeof value !== 'string')
315
- return null;
316
- const trimmed = value.trim();
317
- if (!trimmed)
318
- return null;
319
- const ms = Date.parse(trimmed);
320
- return Number.isFinite(ms) ? ms : null;
321
- }
322
- /** Brief frontmatter date in milliseconds, or null when missing or invalid. */
323
- async function readBriefDateMs(folderPath) {
324
- const content = await fs.readFile(path.join(folderPath, 'brief.md'), 'utf8').catch(() => null);
325
- if (content === null)
326
- return null;
327
- return parseBriefDateMs(parseFrontmatter(content).data);
328
- }
329
- /** Manifest `approvedAt` in milliseconds, or null when missing or invalid. */
317
+ /**
318
+ * Trusted manifest `approvedAt` in milliseconds: the value counts only when the
319
+ * change folder holds `.run/approved`. Null when missing, untrusted, or invalid.
320
+ */
330
321
  async function readApprovedAtMs(folderPath) {
331
- const content = await fs
332
- .readFile(path.join(folderPath, '.run', 'manifest.json'), 'utf8')
333
- .catch(() => null);
334
- if (content === null)
322
+ const approvedAt = await readManifestApprovedAt(folderPath);
323
+ if (approvedAt === null)
335
324
  return null;
336
- try {
337
- const parsed = JSON.parse(content);
338
- if (typeof parsed.approvedAt !== 'string')
339
- return null;
340
- const ms = Date.parse(parsed.approvedAt);
341
- return Number.isFinite(ms) ? ms : null;
342
- }
343
- catch {
344
- return null;
345
- }
325
+ const ms = Date.parse(approvedAt);
326
+ return Number.isFinite(ms) ? ms : null;
346
327
  }
347
328
  /**
348
329
  * Earliest `started` event timestamp across numeric `<n>.jsonl` task streams.
@@ -455,62 +436,78 @@ function aggregatePhase(rows, key) {
455
436
  };
456
437
  }
457
438
  export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
458
- let specsDir = getChangesDir(config.paths.openspecRoot, projectRoot);
459
- let archiveDir = getArchiveDir(config.paths.openspecRoot, projectRoot);
460
- let rejectedDir = getRejectedDir(config.paths.openspecRoot, projectRoot);
439
+ const [tree] = await changeTrees(projectRoot, config);
440
+ let specsDir = tree.changesDir;
441
+ let archiveDir = tree.archiveDir;
442
+ let rejectedDir = tree.rejectedDir;
461
443
  const specsDirStat = await fs.stat(specsDir).catch(() => null);
462
444
  const archiveDirStat = await fs.stat(archiveDir).catch(() => null);
445
+ let legacy = false;
463
446
  if (!specsDirStat && !archiveDirStat) {
464
447
  const legacySpecs = path.join(projectRoot, 'specs');
465
448
  const legacyArchive = path.join(projectRoot, 'specs', 'archive');
466
449
  const legacySpecsStat = await fs.stat(legacySpecs).catch(() => null);
467
450
  const legacyArchiveStat = await fs.stat(legacyArchive).catch(() => null);
468
451
  if (legacySpecsStat || legacyArchiveStat) {
452
+ legacy = true;
469
453
  specsDir = legacySpecs;
470
454
  archiveDir = legacyArchive;
471
455
  rejectedDir = path.join(legacySpecs, 'rejected');
472
456
  }
473
457
  }
474
- // 1. Identify active specs
475
- let activeEntries = [];
476
- try {
477
- activeEntries = await fs.readdir(specsDir);
478
- }
479
- catch {
480
- activeEntries = [];
481
- }
482
- const archiveRel = path.relative(specsDir, archiveDir);
483
- const archiveFolder = !archiveRel.startsWith('..') && !path.isAbsolute(archiveRel)
484
- ? archiveRel.split(path.sep)[0]
485
- : 'archive';
486
- const rejectedRel = path.relative(specsDir, rejectedDir);
487
- const rejectedFolder = !rejectedRel.startsWith('..') && !path.isAbsolute(rejectedRel)
488
- ? rejectedRel.split(path.sep)[0]
489
- : 'rejected';
490
- const candidateActive = activeEntries.filter((e) => !e.startsWith('_') && !e.startsWith('.') && e !== archiveFolder && e !== rejectedFolder);
491
458
  const activeFolders = [];
492
- for (const folder of candidateActive) {
493
- const fullPath = path.join(specsDir, folder);
494
- const stat = await fs.stat(fullPath).catch(() => null);
495
- if (stat?.isDirectory()) {
496
- activeFolders.push(fullPath);
459
+ const archivedFolders = [];
460
+ let rejectedFolders = [];
461
+ if (legacy) {
462
+ // 1. Identify active specs
463
+ let activeEntries = [];
464
+ try {
465
+ activeEntries = await fs.readdir(specsDir);
497
466
  }
467
+ catch {
468
+ activeEntries = [];
469
+ }
470
+ const archiveRel = path.relative(specsDir, archiveDir);
471
+ const archiveFolder = !archiveRel.startsWith('..') && !path.isAbsolute(archiveRel)
472
+ ? archiveRel.split(path.sep)[0]
473
+ : 'archive';
474
+ const rejectedRel = path.relative(specsDir, rejectedDir);
475
+ const rejectedFolder = !rejectedRel.startsWith('..') && !path.isAbsolute(rejectedRel)
476
+ ? rejectedRel.split(path.sep)[0]
477
+ : 'rejected';
478
+ const candidateActive = activeEntries.filter((e) => !e.startsWith('_') && !e.startsWith('.') && e !== archiveFolder && e !== rejectedFolder);
479
+ for (const folder of candidateActive) {
480
+ const fullPath = path.join(specsDir, folder);
481
+ const stat = await fs.stat(fullPath).catch(() => null);
482
+ if (stat?.isDirectory())
483
+ activeFolders.push(fullPath);
484
+ }
485
+ // 2. Identify archived specs
486
+ let archiveEntries = [];
487
+ try {
488
+ archiveEntries = await fs.readdir(archiveDir);
489
+ }
490
+ catch {
491
+ archiveEntries = [];
492
+ }
493
+ for (const folder of archiveEntries) {
494
+ if (folder.startsWith('_') || folder.startsWith('.'))
495
+ continue;
496
+ const fullPath = path.join(archiveDir, folder);
497
+ const stat = await fs.stat(fullPath).catch(() => null);
498
+ if (stat?.isDirectory())
499
+ archivedFolders.push(fullPath);
500
+ }
501
+ rejectedFolders = await listRejectedFolders(rejectedDir);
498
502
  }
499
- // 2. Identify archived specs
500
- let archiveEntries = [];
501
- try {
502
- archiveEntries = await fs.readdir(archiveDir);
503
- }
504
- catch {
505
- archiveEntries = [];
506
- }
507
- const candidateArchived = archiveEntries.filter((e) => !e.startsWith('_') && !e.startsWith('.'));
508
- const archivedFolders = [];
509
- for (const folder of candidateArchived) {
510
- const fullPath = path.join(archiveDir, folder);
511
- const stat = await fs.stat(fullPath).catch(() => null);
512
- if (stat?.isDirectory()) {
513
- archivedFolders.push(fullPath);
503
+ else {
504
+ for (const change of await listChanges(projectRoot, config)) {
505
+ if (change.location === 'active')
506
+ activeFolders.push(change.folderPath);
507
+ else if (change.location === 'archived')
508
+ archivedFolders.push(change.folderPath);
509
+ else
510
+ rejectedFolders.push(change.folderPath);
514
511
  }
515
512
  }
516
513
  const allSpecFolders = [...activeFolders, ...archivedFolders];
@@ -519,7 +516,7 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
519
516
  // other aggregate. A folder counts once, only with a valid `rejected` event.
520
517
  let rejectionTotal = 0;
521
518
  const rejectionsByPlanner = {};
522
- for (const folderPath of await listRejectedFolders(rejectedDir)) {
519
+ for (const folderPath of rejectedFolders) {
523
520
  if (!(await hasRejectedEvent(folderPath)))
524
521
  continue;
525
522
  rejectionTotal++;
@@ -637,6 +634,7 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
637
634
  let scopeVerificationPassed = 0;
638
635
  let scopeVerificationFailed = 0;
639
636
  let scopeRecertifiedByHuman = 0;
637
+ let scopeRecertifiedAutomatically = 0;
640
638
  let scopeRequeuedForAgent = 0;
641
639
  let withEventsCount = 0;
642
640
  let withoutEventsCount = 0;
@@ -688,6 +686,7 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
688
686
  scopeVerificationPassed += observation.scopeVerificationPassed;
689
687
  scopeVerificationFailed += observation.scopeVerificationFailed;
690
688
  scopeRecertifiedByHuman += observation.scopeRecertifiedByHuman;
689
+ scopeRecertifiedAutomatically += observation.scopeRecertifiedAutomatically;
691
690
  scopeRequeuedForAgent += observation.scopeRequeuedForAgent;
692
691
  attemptsByTask[task.id] = taskAttempts;
693
692
  if (taskAttempts > 1)
@@ -872,11 +871,10 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
872
871
  const cycleRows = [];
873
872
  for (const folderPath of archivedFolders) {
874
873
  const change = path.basename(folderPath);
875
- const briefMs = await readBriefDateMs(folderPath);
876
874
  const approvedMs = await readApprovedAtMs(folderPath);
877
875
  const firstStartMs = await readFirstTaskStartMs(folderPath);
878
876
  const archivedMs = await readArchivedAtMs(folderPath);
879
- const briefToApprovalSeconds = phaseSeconds(briefMs, approvedMs);
877
+ const briefToApprovalSeconds = await readBriefToApprovalSeconds(folderPath);
880
878
  const approvalToFirstTaskSeconds = phaseSeconds(approvedMs, firstStartMs);
881
879
  const firstTaskToArchiveSeconds = phaseSeconds(firstStartMs, archivedMs);
882
880
  const totalSeconds = briefToApprovalSeconds !== null &&
@@ -909,7 +907,14 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
909
907
  const formattedTotal = formatDuration(totalDurationMs);
910
908
  const formattedAvg = formatDuration(avgDurationMs);
911
909
  const queue = await readQueueReport(projectRoot, config);
912
- const approvalFlags = await collectApprovalFlagOutcomes(allSpecFolders);
910
+ const rework = await collectRework(allSpecFolders);
911
+ const approvalFlags = await collectApprovalFlagOutcomes(allSpecFolders, rework);
912
+ const disclosures = await collectDisclosures(allSpecFolders);
913
+ const dependencies = await collectDependencies(allSpecFolders);
914
+ const verification = await collectVerificationCounts(archivedFolders);
915
+ const planningCostBySource = await collectCostBySource(allSpecFolders, config.planning?.prices);
916
+ const traceability = await collectTraceabilityGaps(projectRoot, config);
917
+ const mutation = await collectMutationScores(allSpecFolders, config);
913
918
  const measuredTasks = await projectMeasuredTasks(allSpecFolders);
914
919
  const sizes = {
915
920
  scopeFileSeries: deriveScopeFileSeries(measuredTasks),
@@ -984,8 +989,13 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
984
989
  verificationPassedAtDetection: scopeVerificationPassed,
985
990
  verificationFailedAtDetection: scopeVerificationFailed,
986
991
  recertifiedByHuman: scopeRecertifiedByHuman,
992
+ recertifiedAutomatically: scopeRecertifiedAutomatically,
987
993
  requeuedForAgent: scopeRequeuedForAgent,
988
994
  },
995
+ rework,
996
+ disclosures,
997
+ ...(dependencies.length > 0 ? { dependencies } : {}),
998
+ ...(verification ? { verification } : {}),
989
999
  },
990
1000
  coverage: {
991
1001
  withEvents: withEventsCount,
@@ -1034,6 +1044,7 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
1034
1044
  total: planningCost,
1035
1045
  formattedTotal: formatReportedCost(planningCost, planningCostReportedSessions),
1036
1046
  provenance: 'harness-reported',
1047
+ bySource: planningCostBySource,
1037
1048
  },
1038
1049
  coverage: {
1039
1050
  reportedSessions: planningReportedSessions,
@@ -1043,6 +1054,8 @@ export async function getMetricsReport(projectRoot, config = DEFAULT_CONFIG) {
1043
1054
  comparison: planningComparison,
1044
1055
  },
1045
1056
  queue,
1057
+ ...(traceability ? { traceability } : {}),
1058
+ ...(mutation ? { mutation } : {}),
1046
1059
  };
1047
1060
  }
1048
1061
  /**
@@ -1057,25 +1070,9 @@ function numericPrefix(name) {
1057
1070
  const match = name.match(/^(\d+)/);
1058
1071
  return match ? Number.parseInt(match[1], 10) : null;
1059
1072
  }
1060
- /** Canonical archive folders, newest numeric first, hidden entries excluded. */
1061
- async function listRecentArchiveFolders(archiveDir, limit) {
1062
- let entries = [];
1063
- try {
1064
- entries = await fs.readdir(archiveDir);
1065
- }
1066
- catch {
1067
- return [];
1068
- }
1069
- const folders = [];
1070
- for (const entry of entries) {
1071
- if (entry.startsWith('.') || entry.startsWith('_'))
1072
- continue;
1073
- const fullPath = path.join(archiveDir, entry);
1074
- const stat = await fs.stat(fullPath).catch(() => null);
1075
- if (stat?.isDirectory())
1076
- folders.push(fullPath);
1077
- }
1078
- folders.sort((a, b) => {
1073
+ /** Newest archived folders first by numeric prefix, capped at `limit`. */
1074
+ function listRecentArchiveFolders(folders, limit) {
1075
+ const sorted = [...folders].sort((a, b) => {
1079
1076
  const nameA = path.basename(a);
1080
1077
  const nameB = path.basename(b);
1081
1078
  const numA = numericPrefix(nameA);
@@ -1091,7 +1088,7 @@ async function listRecentArchiveFolders(archiveDir, limit) {
1091
1088
  return 1;
1092
1089
  return nameA.localeCompare(nameB);
1093
1090
  });
1094
- return folders.slice(0, limit);
1091
+ return sorted.slice(0, limit);
1095
1092
  }
1096
1093
  /** Every typed `dead` event in the window, in change/task/event order. */
1097
1094
  async function collectDeadOutcomes(folders) {
@@ -1132,8 +1129,8 @@ async function collectDeadOutcomes(folders) {
1132
1129
  * changes by numeric id, with measured outcomes and up to ten dead rows.
1133
1130
  */
1134
1131
  export async function getRepositoryRecord(projectRoot, config = DEFAULT_CONFIG) {
1135
- const archiveDir = getArchiveDir(config.paths.openspecRoot, projectRoot);
1136
- const folders = await listRecentArchiveFolders(archiveDir, REPOSITORY_RECORD_MAX_ARCHIVED_CHANGES);
1132
+ const archived = await listChanges(projectRoot, config, ['archived']);
1133
+ const folders = listRecentArchiveFolders(archived.map((change) => change.folderPath), REPOSITORY_RECORD_MAX_ARCHIVED_CHANGES);
1137
1134
  const measured = await projectMeasuredTasks(folders);
1138
1135
  const deadOutcomes = await collectDeadOutcomes(folders);
1139
1136
  const passed = measured.filter((task) => task.firstAttemptPass).length;
@@ -1150,7 +1147,7 @@ export async function getRepositoryRecord(projectRoot, config = DEFAULT_CONFIG)
1150
1147
  const scopeFileResolver = scopeTasks.length > 0 ? (useResolver2 ? 'resolver-2' : 'legacy') : null;
1151
1148
  return {
1152
1149
  measuredTasks: measured.length,
1153
- firstAttemptPassRate: measured.length > 0 ? round2(passed / measured.length) : 0,
1150
+ firstAttemptPasses: passed,
1154
1151
  medianDurationSeconds: medianSeconds(durations),
1155
1152
  largestFirstAttemptPass: selectLargestFirstAttemptPass(scopeTasks),
1156
1153
  scopeFileResolver,
@@ -1166,7 +1163,7 @@ export function formatRepositoryRecordBody(record) {
1166
1163
  return `This repository's measured record is too small (fewer than ${REPOSITORY_RECORD_MIN_MEASURED_TASKS} tasks).`;
1167
1164
  }
1168
1165
  const lines = [];
1169
- lines.push(`First-attempt pass rate: ${record.firstAttemptPassRate}`);
1166
+ lines.push(`First-attempt passes: ${record.firstAttemptPasses}/${record.measuredTasks}`);
1170
1167
  const largest = record.largestFirstAttemptPass;
1171
1168
  if (largest) {
1172
1169
  const scopeLabel = record.scopeFileResolver === 'legacy'
@@ -1275,7 +1272,16 @@ export function formatMetricsReport(report, config = DEFAULT_CONFIG) {
1275
1272
  lines.push(` Verification passed at detection: ${report.history.scopeRegressions.verificationPassedAtDetection}`);
1276
1273
  lines.push(` Verification failed at detection: ${report.history.scopeRegressions.verificationFailedAtDetection}`);
1277
1274
  lines.push(` Recertified by human: ${report.history.scopeRegressions.recertifiedByHuman}`);
1275
+ lines.push(` Recertified automatically: ${report.history.scopeRegressions.recertifiedAutomatically}`);
1278
1276
  lines.push(` Requeued for agent: ${report.history.scopeRegressions.requeuedForAgent}`);
1277
+ lines.push(...formatRework(report.history.rework ?? []));
1278
+ lines.push(...formatDisclosures(report.history.disclosures ?? []));
1279
+ if ((report.history.dependencies ?? []).length > 0) {
1280
+ lines.push(...formatDependencies(report.history.dependencies ?? []));
1281
+ }
1282
+ if (report.history.verification) {
1283
+ lines.push(formatVerificationCounts(report.history.verification));
1284
+ }
1279
1285
  const scopeSeries = report.history.sizes.scopeFileSeries;
1280
1286
  const legacySeries = scopeSeries.find((entry) => entry.resolver === 'legacy');
1281
1287
  const resolver2Series = scopeSeries.find((entry) => entry.resolver === 'resolver-2');
@@ -1299,6 +1305,14 @@ export function formatMetricsReport(report, config = DEFAULT_CONFIG) {
1299
1305
  lines.push(` Size hint: largest first-attempt pass ${largestPass.change}/${largestPass.task} — ${matching.join('; ')}`);
1300
1306
  }
1301
1307
  }
1308
+ if (report.traceability) {
1309
+ lines.push('');
1310
+ lines.push(...formatTraceability(report.traceability));
1311
+ }
1312
+ if (report.mutation) {
1313
+ lines.push('');
1314
+ lines.push(...formatMutation(report.mutation));
1315
+ }
1302
1316
  lines.push('');
1303
1317
  lines.push('Coverage:');
1304
1318
  lines.push(` Tasks with event files: ${report.coverage.withEvents}`);
@@ -1322,6 +1336,7 @@ export function formatMetricsReport(report, config = DEFAULT_CONFIG) {
1322
1336
  lines.push(` Cached tokens: ${report.planning.tokens.cached}`);
1323
1337
  lines.push(` Reasoning tokens: ${report.planning.tokens.reasoning}`);
1324
1338
  lines.push(` Harness-reported cost: ${report.planning.cost.formattedTotal}`);
1339
+ lines.push(...formatPlanningCostBySource(report.planning.cost.bySource));
1325
1340
  lines.push(` ${report.planning.coverage.reportedSessions} of ${report.planning.coverage.totalSessions} sessions reported usage`);
1326
1341
  lines.push(` ${report.planning.changesWithPlanningRecords} changes have a planning record`);
1327
1342
  const planningChangeEntries = Object.entries(report.planning.byChange).sort(([a], [b]) => a.localeCompare(b));
@@ -1359,6 +1374,10 @@ export function formatMetricsReport(report, config = DEFAULT_CONFIG) {
1359
1374
  ['Total', report.cycle.phases.total],
1360
1375
  ];
1361
1376
  for (const [label, phase] of cyclePhaseLines) {
1377
+ if (phase.coveredChanges === 0) {
1378
+ lines.push(` ${label}: not reported (0 of ${phase.totalChanges} archived changes)`);
1379
+ continue;
1380
+ }
1362
1381
  lines.push(` ${label}: total ${formatDuration(phase.totalSeconds * 1000)}, average ${formatDuration(phase.averageSeconds * 1000)} (${phase.coveredChanges} of ${phase.totalChanges} archived changes)`);
1363
1382
  }
1364
1383
  lines.push('');