@matteeh/osq 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (619) hide show
  1. package/README.md +415 -72
  2. package/dist/cli/approve.d.ts +13 -3
  3. package/dist/cli/approve.d.ts.map +1 -1
  4. package/dist/cli/approve.js +59 -4
  5. package/dist/cli/approve.js.map +1 -1
  6. package/dist/cli/bin.js +0 -0
  7. package/dist/cli/confirm.d.ts +21 -0
  8. package/dist/cli/confirm.d.ts.map +1 -0
  9. package/dist/cli/confirm.js +28 -0
  10. package/dist/cli/confirm.js.map +1 -0
  11. package/dist/cli/doctor.d.ts +13 -0
  12. package/dist/cli/doctor.d.ts.map +1 -0
  13. package/dist/cli/doctor.js +23 -0
  14. package/dist/cli/doctor.js.map +1 -0
  15. package/dist/cli/done.d.ts +12 -0
  16. package/dist/cli/done.d.ts.map +1 -0
  17. package/dist/cli/done.js +26 -0
  18. package/dist/cli/done.js.map +1 -0
  19. package/dist/cli/inbox.d.ts +22 -0
  20. package/dist/cli/inbox.d.ts.map +1 -0
  21. package/dist/cli/inbox.js +41 -0
  22. package/dist/cli/inbox.js.map +1 -0
  23. package/dist/cli/index.d.ts.map +1 -1
  24. package/dist/cli/index.js +127 -8
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/init.d.ts +1 -0
  27. package/dist/cli/init.d.ts.map +1 -1
  28. package/dist/cli/init.js +9 -3
  29. package/dist/cli/init.js.map +1 -1
  30. package/dist/cli/lint.d.ts +26 -0
  31. package/dist/cli/lint.d.ts.map +1 -0
  32. package/dist/cli/lint.js +60 -0
  33. package/dist/cli/lint.js.map +1 -0
  34. package/dist/cli/migrate.d.ts +18 -0
  35. package/dist/cli/migrate.d.ts.map +1 -0
  36. package/dist/cli/migrate.js +42 -0
  37. package/dist/cli/migrate.js.map +1 -0
  38. package/dist/cli/new.js +1 -1
  39. package/dist/cli/new.js.map +1 -1
  40. package/dist/cli/plan-queue.d.ts +50 -0
  41. package/dist/cli/plan-queue.d.ts.map +1 -0
  42. package/dist/cli/plan-queue.js +167 -0
  43. package/dist/cli/plan-queue.js.map +1 -0
  44. package/dist/cli/plan.d.ts +35 -0
  45. package/dist/cli/plan.d.ts.map +1 -0
  46. package/dist/cli/plan.js +153 -0
  47. package/dist/cli/plan.js.map +1 -0
  48. package/dist/cli/queue.d.ts +9 -0
  49. package/dist/cli/queue.d.ts.map +1 -0
  50. package/dist/cli/queue.js +24 -0
  51. package/dist/cli/queue.js.map +1 -0
  52. package/dist/cli/reject.d.ts +8 -0
  53. package/dist/cli/reject.d.ts.map +1 -0
  54. package/dist/cli/reject.js +18 -0
  55. package/dist/cli/reject.js.map +1 -0
  56. package/dist/cli/report.d.ts +1 -1
  57. package/dist/cli/report.d.ts.map +1 -1
  58. package/dist/cli/report.js +141 -14
  59. package/dist/cli/report.js.map +1 -1
  60. package/dist/cli/retry.d.ts +7 -0
  61. package/dist/cli/retry.d.ts.map +1 -0
  62. package/dist/cli/retry.js +29 -0
  63. package/dist/cli/retry.js.map +1 -0
  64. package/dist/cli/serve.d.ts +30 -0
  65. package/dist/cli/serve.d.ts.map +1 -0
  66. package/dist/cli/serve.js +136 -0
  67. package/dist/cli/serve.js.map +1 -0
  68. package/dist/cli/setup.d.ts.map +1 -1
  69. package/dist/cli/setup.js +7 -1
  70. package/dist/cli/setup.js.map +1 -1
  71. package/dist/cli/show.d.ts +2 -1
  72. package/dist/cli/show.d.ts.map +1 -1
  73. package/dist/cli/show.js +20 -3
  74. package/dist/cli/show.js.map +1 -1
  75. package/dist/cli/status.d.ts +1 -1
  76. package/dist/cli/status.d.ts.map +1 -1
  77. package/dist/cli/status.js +2 -2
  78. package/dist/cli/status.js.map +1 -1
  79. package/dist/cli/watch.d.ts +9 -6
  80. package/dist/cli/watch.d.ts.map +1 -1
  81. package/dist/cli/watch.js +15 -2
  82. package/dist/cli/watch.js.map +1 -1
  83. package/dist/core/foundation/config-codex.d.ts +22 -0
  84. package/dist/core/foundation/config-codex.d.ts.map +1 -0
  85. package/dist/core/foundation/config-codex.js +58 -0
  86. package/dist/core/foundation/config-codex.js.map +1 -0
  87. package/dist/core/foundation/config-doctor.d.ts +14 -0
  88. package/dist/core/foundation/config-doctor.d.ts.map +1 -0
  89. package/dist/core/foundation/config-doctor.js +29 -0
  90. package/dist/core/foundation/config-doctor.js.map +1 -0
  91. package/dist/core/foundation/config-env.d.ts +3 -0
  92. package/dist/core/foundation/config-env.d.ts.map +1 -0
  93. package/dist/core/foundation/config-env.js +22 -0
  94. package/dist/core/foundation/config-env.js.map +1 -0
  95. package/dist/core/foundation/config-gates.d.ts +22 -0
  96. package/dist/core/foundation/config-gates.d.ts.map +1 -0
  97. package/dist/core/foundation/config-gates.js +43 -0
  98. package/dist/core/foundation/config-gates.js.map +1 -0
  99. package/dist/core/foundation/config-pi.d.ts +64 -0
  100. package/dist/core/foundation/config-pi.d.ts.map +1 -0
  101. package/dist/core/foundation/config-pi.js +131 -0
  102. package/dist/core/foundation/config-pi.js.map +1 -0
  103. package/dist/core/foundation/config-planning.d.ts +24 -0
  104. package/dist/core/foundation/config-planning.d.ts.map +1 -0
  105. package/dist/core/foundation/config-planning.js +60 -0
  106. package/dist/core/foundation/config-planning.js.map +1 -0
  107. package/dist/core/foundation/config-queue.d.ts +15 -0
  108. package/dist/core/foundation/config-queue.d.ts.map +1 -0
  109. package/dist/core/foundation/config-queue.js +24 -0
  110. package/dist/core/foundation/config-queue.js.map +1 -0
  111. package/dist/core/foundation/config-serve.d.ts +20 -0
  112. package/dist/core/foundation/config-serve.d.ts.map +1 -0
  113. package/dist/core/foundation/config-serve.js +35 -0
  114. package/dist/core/foundation/config-serve.js.map +1 -0
  115. package/dist/core/{config.d.ts → foundation/config.d.ts} +34 -3
  116. package/dist/core/foundation/config.d.ts.map +1 -0
  117. package/dist/core/{config.js → foundation/config.js} +35 -18
  118. package/dist/core/foundation/config.js.map +1 -0
  119. package/dist/core/foundation/doctor-managed.d.ts +13 -0
  120. package/dist/core/foundation/doctor-managed.d.ts.map +1 -0
  121. package/dist/core/foundation/doctor-managed.js +77 -0
  122. package/dist/core/foundation/doctor-managed.js.map +1 -0
  123. package/dist/core/foundation/doctor.d.ts +19 -0
  124. package/dist/core/foundation/doctor.d.ts.map +1 -0
  125. package/dist/core/foundation/doctor.js +187 -0
  126. package/dist/core/foundation/doctor.js.map +1 -0
  127. package/dist/core/foundation/harness-catalog.d.ts +96 -0
  128. package/dist/core/foundation/harness-catalog.d.ts.map +1 -0
  129. package/dist/core/foundation/harness-catalog.js +182 -0
  130. package/dist/core/foundation/harness-catalog.js.map +1 -0
  131. package/dist/core/foundation/init-blocks.d.ts +33 -0
  132. package/dist/core/foundation/init-blocks.d.ts.map +1 -0
  133. package/dist/core/foundation/init-blocks.js +165 -0
  134. package/dist/core/foundation/init-blocks.js.map +1 -0
  135. package/dist/core/foundation/init-managed.d.ts +10 -0
  136. package/dist/core/foundation/init-managed.d.ts.map +1 -0
  137. package/dist/core/foundation/init-managed.js +115 -0
  138. package/dist/core/foundation/init-managed.js.map +1 -0
  139. package/dist/core/foundation/init.d.ts +18 -0
  140. package/dist/core/foundation/init.d.ts.map +1 -0
  141. package/dist/core/foundation/init.js +113 -0
  142. package/dist/core/foundation/init.js.map +1 -0
  143. package/dist/core/{logger.d.ts → foundation/logger.d.ts} +1 -0
  144. package/dist/core/foundation/logger.d.ts.map +1 -0
  145. package/dist/core/{logger.js → foundation/logger.js} +18 -2
  146. package/dist/core/foundation/logger.js.map +1 -0
  147. package/dist/core/{new.d.ts → foundation/new.d.ts} +3 -0
  148. package/dist/core/foundation/new.d.ts.map +1 -0
  149. package/dist/core/foundation/new.js +206 -0
  150. package/dist/core/foundation/new.js.map +1 -0
  151. package/dist/core/foundation/package-root.d.ts +9 -0
  152. package/dist/core/foundation/package-root.d.ts.map +1 -0
  153. package/dist/core/foundation/package-root.js +11 -0
  154. package/dist/core/foundation/package-root.js.map +1 -0
  155. package/dist/core/lifecycle/done.d.ts +17 -0
  156. package/dist/core/lifecycle/done.d.ts.map +1 -0
  157. package/dist/core/lifecycle/done.js +97 -0
  158. package/dist/core/lifecycle/done.js.map +1 -0
  159. package/dist/core/lifecycle/reject.d.ts +26 -0
  160. package/dist/core/lifecycle/reject.d.ts.map +1 -0
  161. package/dist/core/lifecycle/reject.js +83 -0
  162. package/dist/core/lifecycle/reject.js.map +1 -0
  163. package/dist/core/lifecycle/retry-transition.d.ts +23 -0
  164. package/dist/core/lifecycle/retry-transition.d.ts.map +1 -0
  165. package/dist/core/lifecycle/retry-transition.js +41 -0
  166. package/dist/core/lifecycle/retry-transition.js.map +1 -0
  167. package/dist/core/lifecycle/retry.d.ts +18 -0
  168. package/dist/core/lifecycle/retry.d.ts.map +1 -0
  169. package/dist/core/lifecycle/retry.js +179 -0
  170. package/dist/core/lifecycle/retry.js.map +1 -0
  171. package/dist/core/report/approval-flags.d.ts +29 -0
  172. package/dist/core/report/approval-flags.d.ts.map +1 -0
  173. package/dist/core/report/approval-flags.js +138 -0
  174. package/dist/core/report/approval-flags.js.map +1 -0
  175. package/dist/core/report/planning-economics.d.ts +39 -0
  176. package/dist/core/report/planning-economics.d.ts.map +1 -0
  177. package/dist/core/report/planning-economics.js +168 -0
  178. package/dist/core/report/planning-economics.js.map +1 -0
  179. package/dist/core/report/planning-observed.d.ts +59 -0
  180. package/dist/core/report/planning-observed.d.ts.map +1 -0
  181. package/dist/core/report/planning-observed.js +135 -0
  182. package/dist/core/report/planning-observed.js.map +1 -0
  183. package/dist/core/report/planning-records.d.ts +69 -0
  184. package/dist/core/report/planning-records.d.ts.map +1 -0
  185. package/dist/core/report/planning-records.js +149 -0
  186. package/dist/core/report/planning-records.js.map +1 -0
  187. package/dist/core/report/planning-slice-lookup.d.ts +13 -0
  188. package/dist/core/report/planning-slice-lookup.d.ts.map +1 -0
  189. package/dist/core/report/planning-slice-lookup.js +146 -0
  190. package/dist/core/report/planning-slice-lookup.js.map +1 -0
  191. package/dist/core/report/planning-slice-measures.d.ts +17 -0
  192. package/dist/core/report/planning-slice-measures.d.ts.map +1 -0
  193. package/dist/core/report/planning-slice-measures.js +85 -0
  194. package/dist/core/report/planning-slice-measures.js.map +1 -0
  195. package/dist/core/report/planning-slice-record.d.ts +4 -0
  196. package/dist/core/report/planning-slice-record.d.ts.map +1 -0
  197. package/dist/core/report/planning-slice-record.js +66 -0
  198. package/dist/core/report/planning-slice-record.js.map +1 -0
  199. package/dist/core/report/planning-slice-turns.d.ts +13 -0
  200. package/dist/core/report/planning-slice-turns.d.ts.map +1 -0
  201. package/dist/core/report/planning-slice-turns.js +41 -0
  202. package/dist/core/report/planning-slice-turns.js.map +1 -0
  203. package/dist/core/report/planning-slice.d.ts +70 -0
  204. package/dist/core/report/planning-slice.d.ts.map +1 -0
  205. package/dist/core/report/planning-slice.js +147 -0
  206. package/dist/core/report/planning-slice.js.map +1 -0
  207. package/dist/core/report/planning.d.ts +31 -0
  208. package/dist/core/report/planning.d.ts.map +1 -0
  209. package/dist/core/report/planning.js +75 -0
  210. package/dist/core/report/planning.js.map +1 -0
  211. package/dist/core/report/report-events.d.ts +52 -0
  212. package/dist/core/report/report-events.d.ts.map +1 -0
  213. package/dist/core/report/report-events.js +198 -0
  214. package/dist/core/report/report-events.js.map +1 -0
  215. package/dist/core/report/report-pre-spawn.d.ts +25 -0
  216. package/dist/core/report/report-pre-spawn.d.ts.map +1 -0
  217. package/dist/core/report/report-pre-spawn.js +40 -0
  218. package/dist/core/report/report-pre-spawn.js.map +1 -0
  219. package/dist/core/report/report-retries.d.ts +30 -0
  220. package/dist/core/report/report-retries.d.ts.map +1 -0
  221. package/dist/core/report/report-retries.js +100 -0
  222. package/dist/core/report/report-retries.js.map +1 -0
  223. package/dist/core/report/report.d.ts +276 -0
  224. package/dist/core/report/report.d.ts.map +1 -0
  225. package/dist/core/report/report.js +1421 -0
  226. package/dist/core/report/report.js.map +1 -0
  227. package/dist/core/{lock.d.ts → run/lock.d.ts} +6 -0
  228. package/dist/core/run/lock.d.ts.map +1 -0
  229. package/dist/core/{lock.js → run/lock.js} +7 -15
  230. package/dist/core/run/lock.js.map +1 -0
  231. package/dist/core/run/manifest.d.ts +39 -0
  232. package/dist/core/run/manifest.d.ts.map +1 -0
  233. package/dist/core/run/manifest.js +137 -0
  234. package/dist/core/run/manifest.js.map +1 -0
  235. package/dist/core/run/scope-hash.d.ts +71 -0
  236. package/dist/core/run/scope-hash.d.ts.map +1 -0
  237. package/dist/core/run/scope-hash.js +177 -0
  238. package/dist/core/run/scope-hash.js.map +1 -0
  239. package/dist/core/run/scope.d.ts +30 -0
  240. package/dist/core/run/scope.d.ts.map +1 -0
  241. package/dist/core/run/scope.js +193 -0
  242. package/dist/core/run/scope.js.map +1 -0
  243. package/dist/core/run/summary.d.ts +8 -0
  244. package/dist/core/run/summary.d.ts.map +1 -0
  245. package/dist/core/run/summary.js +25 -0
  246. package/dist/core/run/summary.js.map +1 -0
  247. package/dist/core/run/verification.d.ts +23 -0
  248. package/dist/core/run/verification.d.ts.map +1 -0
  249. package/dist/core/run/verification.js +78 -0
  250. package/dist/core/run/verification.js.map +1 -0
  251. package/dist/core/spec/approve.d.ts +31 -0
  252. package/dist/core/spec/approve.d.ts.map +1 -0
  253. package/dist/core/spec/approve.js +111 -0
  254. package/dist/core/spec/approve.js.map +1 -0
  255. package/dist/core/spec/delta.d.ts +77 -0
  256. package/dist/core/spec/delta.d.ts.map +1 -0
  257. package/dist/core/spec/delta.js +581 -0
  258. package/dist/core/spec/delta.js.map +1 -0
  259. package/dist/core/spec/digest-flags.d.ts +21 -0
  260. package/dist/core/spec/digest-flags.d.ts.map +1 -0
  261. package/dist/core/spec/digest-flags.js +194 -0
  262. package/dist/core/spec/digest-flags.js.map +1 -0
  263. package/dist/core/spec/digest-verify-starts.d.ts +5 -0
  264. package/dist/core/spec/digest-verify-starts.d.ts.map +1 -0
  265. package/dist/core/spec/digest-verify-starts.js +31 -0
  266. package/dist/core/spec/digest-verify-starts.js.map +1 -0
  267. package/dist/core/spec/digest.d.ts +42 -0
  268. package/dist/core/spec/digest.d.ts.map +1 -0
  269. package/dist/core/spec/digest.js +170 -0
  270. package/dist/core/spec/digest.js.map +1 -0
  271. package/dist/core/spec/hasher.d.ts +11 -0
  272. package/dist/core/spec/hasher.d.ts.map +1 -0
  273. package/dist/core/{hasher.js → spec/hasher.js} +27 -3
  274. package/dist/core/spec/hasher.js.map +1 -0
  275. package/dist/core/spec/linter.d.ts +79 -0
  276. package/dist/core/spec/linter.d.ts.map +1 -0
  277. package/dist/core/spec/linter.js +826 -0
  278. package/dist/core/spec/linter.js.map +1 -0
  279. package/dist/core/spec/migrate.d.ts +54 -0
  280. package/dist/core/spec/migrate.d.ts.map +1 -0
  281. package/dist/core/spec/migrate.js +297 -0
  282. package/dist/core/spec/migrate.js.map +1 -0
  283. package/dist/core/spec/openspec-version.d.ts +30 -0
  284. package/dist/core/spec/openspec-version.d.ts.map +1 -0
  285. package/dist/core/spec/openspec-version.js +118 -0
  286. package/dist/core/spec/openspec-version.js.map +1 -0
  287. package/dist/core/spec/parser.d.ts +82 -0
  288. package/dist/core/spec/parser.d.ts.map +1 -0
  289. package/dist/core/spec/parser.js +221 -0
  290. package/dist/core/spec/parser.js.map +1 -0
  291. package/dist/core/spec/verify-paths.d.ts +18 -0
  292. package/dist/core/spec/verify-paths.d.ts.map +1 -0
  293. package/dist/core/spec/verify-paths.js +139 -0
  294. package/dist/core/spec/verify-paths.js.map +1 -0
  295. package/dist/core/spec/verify-starts.d.ts +45 -0
  296. package/dist/core/spec/verify-starts.d.ts.map +1 -0
  297. package/dist/core/spec/verify-starts.js +61 -0
  298. package/dist/core/spec/verify-starts.js.map +1 -0
  299. package/dist/core/status/inbox-cursor.d.ts +10 -0
  300. package/dist/core/status/inbox-cursor.d.ts.map +1 -0
  301. package/dist/core/status/inbox-cursor.js +33 -0
  302. package/dist/core/status/inbox-cursor.js.map +1 -0
  303. package/dist/core/status/inbox-projection.d.ts +15 -0
  304. package/dist/core/status/inbox-projection.d.ts.map +1 -0
  305. package/dist/core/status/inbox-projection.js +20 -0
  306. package/dist/core/status/inbox-projection.js.map +1 -0
  307. package/dist/core/status/inbox-text.d.ts +4 -0
  308. package/dist/core/status/inbox-text.d.ts.map +1 -0
  309. package/dist/core/status/inbox-text.js +48 -0
  310. package/dist/core/status/inbox-text.js.map +1 -0
  311. package/dist/core/status/inbox.d.ts +53 -0
  312. package/dist/core/status/inbox.d.ts.map +1 -0
  313. package/dist/core/status/inbox.js +167 -0
  314. package/dist/core/status/inbox.js.map +1 -0
  315. package/dist/core/status/layout.d.ts +29 -0
  316. package/dist/core/status/layout.d.ts.map +1 -0
  317. package/dist/core/status/layout.js +77 -0
  318. package/dist/core/status/layout.js.map +1 -0
  319. package/dist/core/status/queue-parser.d.ts +13 -0
  320. package/dist/core/status/queue-parser.d.ts.map +1 -0
  321. package/dist/core/status/queue-parser.js +88 -0
  322. package/dist/core/status/queue-parser.js.map +1 -0
  323. package/dist/core/status/queue-planning.d.ts +62 -0
  324. package/dist/core/status/queue-planning.d.ts.map +1 -0
  325. package/dist/core/status/queue-planning.js +158 -0
  326. package/dist/core/status/queue-planning.js.map +1 -0
  327. package/dist/core/status/queue-report-detail.d.ts +50 -0
  328. package/dist/core/status/queue-report-detail.d.ts.map +1 -0
  329. package/dist/core/status/queue-report-detail.js +140 -0
  330. package/dist/core/status/queue-report-detail.js.map +1 -0
  331. package/dist/core/status/queue-report.d.ts +14 -0
  332. package/dist/core/status/queue-report.d.ts.map +1 -0
  333. package/dist/core/status/queue-report.js +41 -0
  334. package/dist/core/status/queue-report.js.map +1 -0
  335. package/dist/core/status/queue-state.d.ts +53 -0
  336. package/dist/core/status/queue-state.d.ts.map +1 -0
  337. package/dist/core/status/queue-state.js +167 -0
  338. package/dist/core/status/queue-state.js.map +1 -0
  339. package/dist/core/status/queue.d.ts +7 -0
  340. package/dist/core/status/queue.d.ts.map +1 -0
  341. package/dist/core/status/queue.js +4 -0
  342. package/dist/core/status/queue.js.map +1 -0
  343. package/dist/core/status/show.d.ts +102 -0
  344. package/dist/core/status/show.d.ts.map +1 -0
  345. package/dist/core/status/show.js +704 -0
  346. package/dist/core/status/show.js.map +1 -0
  347. package/dist/core/status/state.d.ts +56 -0
  348. package/dist/core/status/state.d.ts.map +1 -0
  349. package/dist/core/status/state.js +187 -0
  350. package/dist/core/status/state.js.map +1 -0
  351. package/dist/core/status/status.d.ts +23 -0
  352. package/dist/core/status/status.d.ts.map +1 -0
  353. package/dist/core/status/status.js +173 -0
  354. package/dist/core/status/status.js.map +1 -0
  355. package/dist/core/web/web-data-change.d.ts +10 -0
  356. package/dist/core/web/web-data-change.d.ts.map +1 -0
  357. package/dist/core/web/web-data-change.js +106 -0
  358. package/dist/core/web/web-data-change.js.map +1 -0
  359. package/dist/core/web/web-data-folders.d.ts +39 -0
  360. package/dist/core/web/web-data-folders.d.ts.map +1 -0
  361. package/dist/core/web/web-data-folders.js +125 -0
  362. package/dist/core/web/web-data-folders.js.map +1 -0
  363. package/dist/core/web/web-data-graph.d.ts +8 -0
  364. package/dist/core/web/web-data-graph.d.ts.map +1 -0
  365. package/dist/core/web/web-data-graph.js +113 -0
  366. package/dist/core/web/web-data-graph.js.map +1 -0
  367. package/dist/core/web/web-data-lifecycle.d.ts +43 -0
  368. package/dist/core/web/web-data-lifecycle.d.ts.map +1 -0
  369. package/dist/core/web/web-data-lifecycle.js +141 -0
  370. package/dist/core/web/web-data-lifecycle.js.map +1 -0
  371. package/dist/core/web/web-data-observations.d.ts +30 -0
  372. package/dist/core/web/web-data-observations.d.ts.map +1 -0
  373. package/dist/core/web/web-data-observations.js +181 -0
  374. package/dist/core/web/web-data-observations.js.map +1 -0
  375. package/dist/core/web/web-data-tokens.d.ts +29 -0
  376. package/dist/core/web/web-data-tokens.d.ts.map +1 -0
  377. package/dist/core/web/web-data-tokens.js +62 -0
  378. package/dist/core/web/web-data-tokens.js.map +1 -0
  379. package/dist/core/web/web-data-types.d.ts +156 -0
  380. package/dist/core/web/web-data-types.d.ts.map +1 -0
  381. package/dist/core/web/web-data-types.js +15 -0
  382. package/dist/core/web/web-data-types.js.map +1 -0
  383. package/dist/core/web/web-data.d.ts +10 -0
  384. package/dist/core/web/web-data.d.ts.map +1 -0
  385. package/dist/core/web/web-data.js +8 -0
  386. package/dist/core/web/web-data.js.map +1 -0
  387. package/dist/core/web/web-events.d.ts +54 -0
  388. package/dist/core/web/web-events.d.ts.map +1 -0
  389. package/dist/core/web/web-events.js +162 -0
  390. package/dist/core/web/web-events.js.map +1 -0
  391. package/dist/core/web/web-export.d.ts +18 -0
  392. package/dist/core/web/web-export.d.ts.map +1 -0
  393. package/dist/core/web/web-export.js +112 -0
  394. package/dist/core/web/web-export.js.map +1 -0
  395. package/dist/core/web/web-server.d.ts +34 -0
  396. package/dist/core/web/web-server.d.ts.map +1 -0
  397. package/dist/core/web/web-server.js +182 -0
  398. package/dist/core/web/web-server.js.map +1 -0
  399. package/dist/core/web/web-static.d.ts +20 -0
  400. package/dist/core/web/web-static.d.ts.map +1 -0
  401. package/dist/core/web/web-static.js +104 -0
  402. package/dist/core/web/web-static.js.map +1 -0
  403. package/dist/harness/{agy.d.ts → agy/agy.d.ts} +8 -6
  404. package/dist/harness/agy/agy.d.ts.map +1 -0
  405. package/dist/harness/{agy.js → agy/agy.js} +49 -34
  406. package/dist/harness/agy/agy.js.map +1 -0
  407. package/dist/harness/claude/claude-turns.d.ts +29 -0
  408. package/dist/harness/claude/claude-turns.d.ts.map +1 -0
  409. package/dist/harness/claude/claude-turns.js +162 -0
  410. package/dist/harness/claude/claude-turns.js.map +1 -0
  411. package/dist/harness/claude/claude-usage.d.ts +12 -0
  412. package/dist/harness/claude/claude-usage.d.ts.map +1 -0
  413. package/dist/harness/claude/claude-usage.js +144 -0
  414. package/dist/harness/claude/claude-usage.js.map +1 -0
  415. package/dist/harness/codex/codex-observe-usage.d.ts +6 -0
  416. package/dist/harness/codex/codex-observe-usage.d.ts.map +1 -0
  417. package/dist/harness/codex/codex-observe-usage.js +215 -0
  418. package/dist/harness/codex/codex-observe-usage.js.map +1 -0
  419. package/dist/harness/codex/codex-prompt.d.ts +17 -0
  420. package/dist/harness/codex/codex-prompt.d.ts.map +1 -0
  421. package/dist/harness/codex/codex-prompt.js +43 -0
  422. package/dist/harness/codex/codex-prompt.js.map +1 -0
  423. package/dist/harness/codex/codex-stream.d.ts +23 -0
  424. package/dist/harness/codex/codex-stream.d.ts.map +1 -0
  425. package/dist/harness/codex/codex-stream.js +182 -0
  426. package/dist/harness/codex/codex-stream.js.map +1 -0
  427. package/dist/harness/codex/codex-usage.d.ts +26 -0
  428. package/dist/harness/codex/codex-usage.d.ts.map +1 -0
  429. package/dist/harness/codex/codex-usage.js +122 -0
  430. package/dist/harness/codex/codex-usage.js.map +1 -0
  431. package/dist/harness/codex/codex.d.ts +16 -0
  432. package/dist/harness/codex/codex.d.ts.map +1 -0
  433. package/dist/harness/codex/codex.js +92 -0
  434. package/dist/harness/codex/codex.js.map +1 -0
  435. package/dist/harness/index.d.ts +11 -2
  436. package/dist/harness/index.d.ts.map +1 -1
  437. package/dist/harness/index.js +24 -9
  438. package/dist/harness/index.js.map +1 -1
  439. package/dist/harness/mock.d.ts +5 -2
  440. package/dist/harness/mock.d.ts.map +1 -1
  441. package/dist/harness/mock.js +10 -11
  442. package/dist/harness/mock.js.map +1 -1
  443. package/dist/harness/opencode/opencode-observe-usage.d.ts +4 -0
  444. package/dist/harness/opencode/opencode-observe-usage.d.ts.map +1 -0
  445. package/dist/harness/opencode/opencode-observe-usage.js +100 -0
  446. package/dist/harness/opencode/opencode-observe-usage.js.map +1 -0
  447. package/dist/harness/opencode/opencode-usage.d.ts +24 -0
  448. package/dist/harness/opencode/opencode-usage.d.ts.map +1 -0
  449. package/dist/harness/opencode/opencode-usage.js +181 -0
  450. package/dist/harness/opencode/opencode-usage.js.map +1 -0
  451. package/dist/harness/{opencode.d.ts → opencode/opencode.d.ts} +10 -7
  452. package/dist/harness/opencode/opencode.d.ts.map +1 -0
  453. package/dist/harness/{opencode.js → opencode/opencode.js} +159 -70
  454. package/dist/harness/opencode/opencode.js.map +1 -0
  455. package/dist/harness/pi/pi-args.d.ts +9 -0
  456. package/dist/harness/pi/pi-args.d.ts.map +1 -0
  457. package/dist/harness/pi/pi-args.js +33 -0
  458. package/dist/harness/pi/pi-args.js.map +1 -0
  459. package/dist/harness/pi/pi-stream.d.ts +27 -0
  460. package/dist/harness/pi/pi-stream.d.ts.map +1 -0
  461. package/dist/harness/pi/pi-stream.js +176 -0
  462. package/dist/harness/pi/pi-stream.js.map +1 -0
  463. package/dist/harness/pi/pi-tools.d.ts +5 -0
  464. package/dist/harness/pi/pi-tools.d.ts.map +1 -0
  465. package/dist/harness/pi/pi-tools.js +31 -0
  466. package/dist/harness/pi/pi-tools.js.map +1 -0
  467. package/dist/harness/pi/pi.d.ts +11 -0
  468. package/dist/harness/pi/pi.d.ts.map +1 -0
  469. package/dist/harness/pi/pi.js +109 -0
  470. package/dist/harness/pi/pi.js.map +1 -0
  471. package/dist/harness/prompt.d.ts +11 -0
  472. package/dist/harness/prompt.d.ts.map +1 -0
  473. package/dist/harness/prompt.js +105 -0
  474. package/dist/harness/prompt.js.map +1 -0
  475. package/dist/harness/types.d.ts +287 -8
  476. package/dist/harness/types.d.ts.map +1 -1
  477. package/dist/harness/types.js +125 -0
  478. package/dist/harness/types.js.map +1 -1
  479. package/dist/index.d.ts +13 -2
  480. package/dist/index.d.ts.map +1 -1
  481. package/dist/index.js +8 -1
  482. package/dist/index.js.map +1 -1
  483. package/dist/watcher/archive-verify.d.ts +9 -0
  484. package/dist/watcher/archive-verify.d.ts.map +1 -0
  485. package/dist/watcher/archive-verify.js +80 -0
  486. package/dist/watcher/archive-verify.js.map +1 -0
  487. package/dist/watcher/archiver.d.ts +14 -2
  488. package/dist/watcher/archiver.d.ts.map +1 -1
  489. package/dist/watcher/archiver.js +112 -33
  490. package/dist/watcher/archiver.js.map +1 -1
  491. package/dist/watcher/attempt.d.ts +19 -0
  492. package/dist/watcher/attempt.d.ts.map +1 -0
  493. package/dist/watcher/attempt.js +94 -0
  494. package/dist/watcher/attempt.js.map +1 -0
  495. package/dist/watcher/auto-retry.d.ts +11 -0
  496. package/dist/watcher/auto-retry.d.ts.map +1 -0
  497. package/dist/watcher/auto-retry.js +180 -0
  498. package/dist/watcher/auto-retry.js.map +1 -0
  499. package/dist/watcher/build.d.ts +24 -0
  500. package/dist/watcher/build.d.ts.map +1 -0
  501. package/dist/watcher/build.js +169 -0
  502. package/dist/watcher/build.js.map +1 -0
  503. package/dist/watcher/change-verify.d.ts +25 -0
  504. package/dist/watcher/change-verify.d.ts.map +1 -0
  505. package/dist/watcher/change-verify.js +57 -0
  506. package/dist/watcher/change-verify.js.map +1 -0
  507. package/dist/watcher/dev.d.ts +51 -0
  508. package/dist/watcher/dev.d.ts.map +1 -0
  509. package/dist/watcher/dev.js +124 -0
  510. package/dist/watcher/dev.js.map +1 -0
  511. package/dist/watcher/failure-reason.d.ts +7 -0
  512. package/dist/watcher/failure-reason.d.ts.map +1 -0
  513. package/dist/watcher/failure-reason.js +2 -0
  514. package/dist/watcher/failure-reason.js.map +1 -0
  515. package/dist/watcher/fingerprint.d.ts +19 -0
  516. package/dist/watcher/fingerprint.d.ts.map +1 -0
  517. package/dist/watcher/fingerprint.js +53 -0
  518. package/dist/watcher/fingerprint.js.map +1 -0
  519. package/dist/watcher/heartbeat.d.ts +33 -0
  520. package/dist/watcher/heartbeat.d.ts.map +1 -0
  521. package/dist/watcher/heartbeat.js +135 -0
  522. package/dist/watcher/heartbeat.js.map +1 -0
  523. package/dist/watcher/lock.d.ts +10 -0
  524. package/dist/watcher/lock.d.ts.map +1 -0
  525. package/dist/watcher/lock.js +14 -0
  526. package/dist/watcher/lock.js.map +1 -0
  527. package/dist/watcher/loop.d.ts +26 -6
  528. package/dist/watcher/loop.d.ts.map +1 -1
  529. package/dist/watcher/loop.js +154 -37
  530. package/dist/watcher/loop.js.map +1 -1
  531. package/dist/watcher/measures.d.ts +46 -0
  532. package/dist/watcher/measures.d.ts.map +1 -0
  533. package/dist/watcher/measures.js +203 -0
  534. package/dist/watcher/measures.js.map +1 -0
  535. package/dist/watcher/outcome.d.ts +32 -0
  536. package/dist/watcher/outcome.d.ts.map +1 -0
  537. package/dist/watcher/outcome.js +127 -0
  538. package/dist/watcher/outcome.js.map +1 -0
  539. package/dist/watcher/regression.d.ts +43 -0
  540. package/dist/watcher/regression.d.ts.map +1 -0
  541. package/dist/watcher/regression.js +175 -0
  542. package/dist/watcher/regression.js.map +1 -0
  543. package/dist/watcher/runner.d.ts +6 -68
  544. package/dist/watcher/runner.d.ts.map +1 -1
  545. package/dist/watcher/runner.js +74 -523
  546. package/dist/watcher/runner.js.map +1 -1
  547. package/dist/watcher/spawn.d.ts +48 -0
  548. package/dist/watcher/spawn.d.ts.map +1 -0
  549. package/dist/watcher/spawn.js +130 -0
  550. package/dist/watcher/spawn.js.map +1 -0
  551. package/dist/watcher/task-verify.d.ts +59 -0
  552. package/dist/watcher/task-verify.d.ts.map +1 -0
  553. package/dist/watcher/task-verify.js +108 -0
  554. package/dist/watcher/task-verify.js.map +1 -0
  555. package/dist/watcher/verify.d.ts +44 -0
  556. package/dist/watcher/verify.d.ts.map +1 -0
  557. package/dist/watcher/verify.js +156 -0
  558. package/dist/watcher/verify.js.map +1 -0
  559. package/package.json +21 -9
  560. package/templates/PLANNER.md +77 -0
  561. package/templates/openspec/config.yaml +24 -0
  562. package/templates/openspec/schemas/osq/README.md +30 -0
  563. package/templates/openspec/schemas/osq/schema.yaml +133 -0
  564. package/templates/openspec/schemas/osq/templates/proposal.md +66 -0
  565. package/templates/openspec/schemas/osq/templates/spec.md +13 -0
  566. package/templates/openspec/schemas/osq/templates/tasks.md +11 -0
  567. package/templates/proposal.md +66 -0
  568. package/templates/tasks.md +5 -0
  569. package/ui/dist/assets/index-CZYeQ8la.js +9 -0
  570. package/ui/dist/assets/index-D6zVSjO7.css +1 -0
  571. package/ui/dist/index.html +14 -0
  572. package/dist/core/approve.d.ts +0 -11
  573. package/dist/core/approve.d.ts.map +0 -1
  574. package/dist/core/approve.js +0 -52
  575. package/dist/core/approve.js.map +0 -1
  576. package/dist/core/config.d.ts.map +0 -1
  577. package/dist/core/config.js.map +0 -1
  578. package/dist/core/hasher.d.ts +0 -4
  579. package/dist/core/hasher.d.ts.map +0 -1
  580. package/dist/core/hasher.js.map +0 -1
  581. package/dist/core/init.d.ts +0 -12
  582. package/dist/core/init.d.ts.map +0 -1
  583. package/dist/core/init.js +0 -151
  584. package/dist/core/init.js.map +0 -1
  585. package/dist/core/linter.d.ts +0 -8
  586. package/dist/core/linter.d.ts.map +0 -1
  587. package/dist/core/linter.js +0 -100
  588. package/dist/core/linter.js.map +0 -1
  589. package/dist/core/lock.d.ts.map +0 -1
  590. package/dist/core/lock.js.map +0 -1
  591. package/dist/core/logger.d.ts.map +0 -1
  592. package/dist/core/logger.js.map +0 -1
  593. package/dist/core/new.d.ts.map +0 -1
  594. package/dist/core/new.js +0 -79
  595. package/dist/core/new.js.map +0 -1
  596. package/dist/core/parser.d.ts +0 -32
  597. package/dist/core/parser.d.ts.map +0 -1
  598. package/dist/core/parser.js +0 -87
  599. package/dist/core/parser.js.map +0 -1
  600. package/dist/core/report.d.ts +0 -54
  601. package/dist/core/report.d.ts.map +0 -1
  602. package/dist/core/report.js +0 -475
  603. package/dist/core/report.js.map +0 -1
  604. package/dist/core/show.d.ts +0 -50
  605. package/dist/core/show.d.ts.map +0 -1
  606. package/dist/core/show.js +0 -374
  607. package/dist/core/show.js.map +0 -1
  608. package/dist/core/state.d.ts +0 -25
  609. package/dist/core/state.d.ts.map +0 -1
  610. package/dist/core/state.js +0 -180
  611. package/dist/core/state.js.map +0 -1
  612. package/dist/core/status.d.ts +0 -10
  613. package/dist/core/status.d.ts.map +0 -1
  614. package/dist/core/status.js +0 -106
  615. package/dist/core/status.js.map +0 -1
  616. package/dist/harness/agy.d.ts.map +0 -1
  617. package/dist/harness/agy.js.map +0 -1
  618. package/dist/harness/opencode.d.ts.map +0 -1
  619. package/dist/harness/opencode.js.map +0 -1
@@ -1,302 +1,26 @@
1
- import { spawn } from 'node:child_process';
2
1
  import fs from 'node:fs/promises';
3
2
  import path from 'node:path';
4
- import { hashChangeFolder } from '../core/hasher.js';
5
- import { acquireLock, releaseLock } from '../core/lock.js';
6
- import { resolveSymbol } from '../core/logger.js';
7
- import { parseTaskMd } from '../core/parser.js';
8
- import { asRecord } from '../harness/stream.js';
9
- import { appendHarnessEvent, } from '../harness/types.js';
10
- /**
11
- * Single-line, human-readable summary of a task outcome. Kept pure so the exact
12
- * shape can be tested without running the runner, and used directly beside every
13
- * marker write (`done/<n>` or `dead/<n>.md`) so the log and the marker agree.
14
- */
15
- export function formatTaskOutcomeSummary(taskNumber, success, reason, extra) {
16
- if (success) {
17
- return `task ${taskNumber} verified (passed)`;
18
- }
19
- const detail = extra ? `, ${extra}` : '';
20
- return `task ${taskNumber} dead (reason: ${reason}${detail})`;
21
- }
22
- export async function tickTaskCheckbox(specFolderPath, taskNumber) {
23
- const tasksMdPath = path.join(specFolderPath, 'tasks.md');
24
- let content = '';
25
- try {
26
- content = await fs.readFile(tasksMdPath, 'utf8');
27
- }
28
- catch {
29
- return;
30
- }
31
- const regex = new RegExp(`^(\\s*-\\s*\\[)[ ](\\]\\s*${taskNumber}\\b.*)$`, 'm');
32
- const updated = content.replace(regex, '$1x$2');
33
- if (updated !== content) {
34
- await fs.writeFile(tasksMdPath, updated, 'utf8');
35
- }
36
- }
37
- /**
38
- * Single code path for process lifecycle observation: the events.jsonl entry and
39
- * its human readable summary are always emitted together.
40
- */
41
- async function recordLifecycleEvent(specFolderPath, taskNumber, event, summary, logger, level = 'info') {
42
- await appendHarnessEvent(specFolderPath, taskNumber, event);
43
- if (level === 'verbose') {
44
- logger?.verbose(summary);
45
- }
46
- else {
47
- logger?.info(summary);
48
- }
49
- }
50
- /**
51
- * Append the `dead` event that always travels with a dead marker. The event
52
- * stream is the append-only source of truth for failure history, so it must
53
- * agree with the marker at every exit. A lock collision never writes a dead
54
- * marker and therefore never records a dead event.
55
- */
56
- async function recordDeadEvent(specFolderPath, taskNumber, reason) {
57
- await appendHarnessEvent(specFolderPath, taskNumber, {
58
- type: 'dead',
59
- timestamp: new Date().toISOString(),
60
- data: { task: taskNumber, reason },
61
- });
62
- }
63
- /**
64
- * Append the `done` event that always travels with a `done/<n>` marker.
65
- */
66
- async function recordDoneEvent(specFolderPath, taskNumber) {
67
- await appendHarnessEvent(specFolderPath, taskNumber, {
68
- type: 'done',
69
- timestamp: new Date().toISOString(),
70
- data: { task: taskNumber },
71
- });
72
- }
73
- const heartbeatAccumulators = new Map();
74
- function createHeartbeatAccumulator() {
75
- return { byteOffset: 0, eventCount: 0, totalTokens: 0, toolCount: 0, cost: 0, hasCost: false };
76
- }
77
- /**
78
- * Snapshot of task progress. Counters are maintained in memory and advanced
79
- * with only the bytes appended since the previous poll; the event file may not
80
- * exist yet, in which case counters are zero.
81
- */
82
- export async function computeTaskHeartbeatStats(specFolderPath, taskNumber, startTime) {
83
- const elapsedSeconds = Number(((Date.now() - startTime) / 1000).toFixed(1));
84
- const eventFilePath = path.join(specFolderPath, '.run', 'events', `${taskNumber}.jsonl`);
85
- let content = '';
86
- try {
87
- content = await fs.readFile(eventFilePath, 'utf8');
88
- }
89
- catch {
90
- heartbeatAccumulators.delete(eventFilePath);
91
- return { elapsedSeconds, eventCount: 0, totalTokens: 0, toolCount: 0 };
92
- }
93
- let accumulator = heartbeatAccumulators.get(eventFilePath);
94
- if (!accumulator || accumulator.byteOffset > content.length) {
95
- accumulator = createHeartbeatAccumulator();
96
- }
97
- const fresh = content.slice(accumulator.byteOffset);
98
- const lastNewline = fresh.lastIndexOf('\n');
99
- if (lastNewline !== -1) {
100
- const complete = fresh.slice(0, lastNewline);
101
- accumulator.byteOffset += lastNewline + 1;
102
- for (const line of complete.split('\n')) {
103
- if (!line.trim()) {
104
- continue;
105
- }
106
- accumulator.eventCount += 1;
107
- let parsed;
108
- try {
109
- parsed = JSON.parse(line);
110
- }
111
- catch {
112
- // Ignore malformed lines rather than losing the whole heartbeat.
113
- continue;
114
- }
115
- const event = asRecord(parsed);
116
- if (!event) {
117
- continue;
118
- }
119
- const data = asRecord(event.data);
120
- if (event.type === 'tokens') {
121
- accumulator.totalTokens += Number(data?.totalTokens ?? 0) || 0;
122
- const cost = Number(data?.cost);
123
- if (Number.isFinite(cost)) {
124
- accumulator.cost += cost;
125
- accumulator.hasCost = true;
126
- }
127
- }
128
- else if (event.type === 'tool') {
129
- accumulator.toolCount += 1;
130
- const summary = data?.summary;
131
- if (typeof summary === 'string') {
132
- accumulator.lastToolSummary = summary;
133
- }
134
- }
135
- }
136
- }
137
- heartbeatAccumulators.set(eventFilePath, accumulator);
138
- const stats = {
139
- elapsedSeconds,
140
- eventCount: accumulator.eventCount,
141
- totalTokens: accumulator.totalTokens,
142
- toolCount: accumulator.toolCount,
143
- };
144
- if (accumulator.hasCost) {
145
- stats.cost = accumulator.cost;
146
- }
147
- if (accumulator.lastToolSummary !== undefined) {
148
- stats.lastToolSummary = accumulator.lastToolSummary;
149
- }
150
- return stats;
151
- }
152
- /**
153
- * Drop the in-memory counters for a finished task so the map does not grow
154
- * across watcher cycles.
155
- */
156
- export function clearTaskHeartbeatStats(specFolderPath, taskNumber) {
157
- const eventFilePath = path.join(specFolderPath, '.run', 'events', `${taskNumber}.jsonl`);
158
- heartbeatAccumulators.delete(eventFilePath);
159
- }
160
- const STATUS_SPINNER_PREFIX_WIDTH = 2; // spinner frame plus a single space
161
- const ELLIPSIS = '…';
162
- function truncateToWidth(text, width) {
163
- if (width <= 0) {
164
- return '';
165
- }
166
- if (text.length <= width) {
167
- return text;
168
- }
169
- if (width === 1) {
170
- return ELLIPSIS;
171
- }
172
- return `${text.slice(0, width - 1)}${ELLIPSIS}`;
173
- }
174
- /**
175
- * Single-line running status row. The logger owns the animated spinner and
176
- * prepends `<frame> `, so this text is truncated to leave room for that prefix
177
- * while fitting `terminalWidth` columns.
178
- */
179
- export function formatTaskStatusRow(taskNumber, stats, terminalWidth = process.stderr.columns ?? 80) {
180
- const segments = [
181
- `task ${taskNumber}`,
182
- `${stats.elapsedSeconds}s`,
183
- `${stats.toolCount} tools`,
184
- `${stats.totalTokens} tokens`,
185
- ];
186
- if (typeof stats.cost === 'number' && Number.isFinite(stats.cost)) {
187
- segments.push(`$${stats.cost.toFixed(4)}`);
188
- }
189
- const budget = terminalWidth - STATUS_SPINNER_PREFIX_WIDTH;
190
- const base = segments.join(' · ');
191
- if (!stats.lastToolSummary) {
192
- return truncateToWidth(base, budget);
193
- }
194
- const separator = ' · ';
195
- const summaryBudget = budget - base.length - separator.length;
196
- if (summaryBudget <= 1) {
197
- return truncateToWidth(base, budget);
198
- }
199
- return `${base}${separator}${truncateToWidth(stats.lastToolSummary, summaryBudget)}`;
200
- }
201
- /** Periodic heartbeat line shared by the 1s TTY row and the non-TTY log. */
202
- export function formatTaskHeartbeatLine(taskNumber, stats) {
203
- return `task ${taskNumber} heartbeat (elapsed: ${stats.elapsedSeconds}s, events: ${stats.eventCount}, tokens: ${stats.totalTokens})`;
204
- }
205
- /**
206
- * Curated task-started line: a single info line carrying the task title
207
- * truncated so the whole line fits the terminal width. The lifecycle details
208
- * (pid, timeout) travel with it so the marker and the log line stay in sync.
209
- */
210
- export function formatTaskStartedLine(taskNumber, title, pid, timeoutSeconds, symbols, terminalWidth = process.stderr.columns ?? 80) {
211
- const symbol = resolveSymbol('▶', '[task]', symbols);
212
- const prefix = `${symbol} task ${taskNumber} started (pid: ${pid ?? 'unknown'}, timeout: ${timeoutSeconds}s): `;
213
- const budget = Math.max(0, terminalWidth - prefix.length);
214
- return `${prefix}${truncateToWidth(title, budget)}`;
215
- }
216
- /**
217
- * Curated task-outcome line: verified or dead with the failure reason and the
218
- * elapsed seconds since the task began.
219
- */
220
- export function formatTaskOutcomeLine(taskNumber, success, reason, elapsedSeconds, symbols) {
221
- if (success) {
222
- return `${resolveSymbol('✓', '[ok]', symbols)} task ${taskNumber} verified (elapsed: ${elapsedSeconds}s)`;
223
- }
224
- return `${resolveSymbol('✗', '[dead]', symbols)} task ${taskNumber} dead (reason: ${reason}, elapsed: ${elapsedSeconds}s)`;
225
- }
226
- /**
227
- * Return the last text message emitted on the agent's event stream, or null
228
- * when the stream has no text at all. Synthesis reads exclusively from
229
- * first-class `text` events carrying the completed assistant message; raw
230
- * harness payload shapes are never inspected. The stream is the append-only
231
- * `.run/events/<n>.jsonl` file, so this survives a watcher restart.
232
- */
233
- export async function extractFinalTextFromStream(specFolderPath, taskNumber) {
234
- const eventFilePath = path.join(specFolderPath, '.run', 'events', `${taskNumber}.jsonl`);
235
- let content = '';
236
- try {
237
- content = await fs.readFile(eventFilePath, 'utf8');
238
- }
239
- catch {
240
- return null;
241
- }
242
- let finalText = null;
243
- for (const line of content.split('\n')) {
244
- if (!line.trim()) {
245
- continue;
246
- }
247
- let parsed;
248
- try {
249
- parsed = JSON.parse(line);
250
- }
251
- catch {
252
- continue;
253
- }
254
- const event = asRecord(parsed);
255
- if (event?.type !== 'text') {
256
- continue;
257
- }
258
- const text = asRecord(event.data)?.text;
259
- if (typeof text === 'string' && text.trim().length > 0) {
260
- finalText = text;
261
- }
262
- }
263
- return finalText?.trim() ? finalText : null;
264
- }
265
- /**
266
- * Write a result file synthesized from the agent's final stream message. The
267
- * frontmatter flags it as `synthesized: true` and a comment attributes it to
268
- * the watcher so a reader never mistakes it for an agent-authored result.
269
- */
270
- export async function synthesizeResultFile(resultsDir, taskNumber, finalText) {
271
- await fs.mkdir(resultsDir, { recursive: true });
272
- const resultPath = path.join(resultsDir, `${taskNumber}.md`);
273
- const body = finalText.endsWith('\n') ? finalText : `${finalText}\n`;
274
- const content = [
275
- '---',
276
- 'synthesized: true',
277
- '---',
278
- "<!-- Synthesized by the osq watcher from the agent's final stream message.",
279
- ' The agent exited without writing a result file. -->',
280
- '',
281
- body,
282
- ].join('\n');
283
- await fs.writeFile(resultPath, content, 'utf8');
284
- return resultPath;
285
- }
3
+ import { hashChangeFolder } from '../core/spec/hasher.js';
4
+ import { parseTaskMd } from '../core/spec/parser.js';
5
+ import { runChangeVerifyGate } from './change-verify.js';
6
+ import { clearTaskHeartbeatStats, computeTaskHeartbeatStats, formatTaskHeartbeatLine, formatTaskStatusRow, } from './heartbeat.js';
7
+ import { acquireTaskLock, releaseTaskLock } from './lock.js';
8
+ import { createTaskMeasures } from './measures.js';
9
+ import { formatTaskOutcomeLine, recordDeadEvent, recordDoneEvent, tickTaskCheckbox, writeDeadMarker, writeDoneMarker, } from './outcome.js';
10
+ import { buildDoneMetadata, guardScopeRegression } from './regression.js';
11
+ import { ensureTaskResult, spawnTaskAgent } from './spawn.js';
12
+ import { checkMissingVerifyPaths, runPreSpawnVerify, verifyRedFailure } from './task-verify.js';
13
+ import { captureTestGate, findUndeclaredTestChanges, runVerificationGate } from './verify.js';
14
+ /** Top-level sequential task pipeline; each phase delegates to its lifecycle module. */
286
15
  export async function runTask(projectRoot, specFolderPath, taskNumber, config, adapter, logger) {
287
16
  const runDir = path.join(specFolderPath, '.run');
288
- const deadDir = path.join(runDir, 'dead');
289
- const doneDir = path.join(runDir, 'done');
290
17
  const startTime = Date.now();
291
18
  const useSymbols = logger?.symbols === true;
292
19
  const interactive = logger?.interactive === true;
293
- const heartbeatSeconds = config.log?.heartbeatSeconds ?? 60;
294
- const heartbeatIntervalMs = heartbeatSeconds * 1000;
20
+ const heartbeatIntervalMs = (config.log?.heartbeatSeconds ?? 60) * 1000;
295
21
  let heartbeatTimer = null;
296
22
  let heartbeatActive = true;
297
23
  let lastHeartbeatLogAt = startTime;
298
- // One timer owns both observation modes: the 1s TTY status row and the
299
- // periodic non-TTY heartbeat log. TTY heartbeats are demoted to verbose.
300
24
  const stopHeartbeat = () => {
301
25
  heartbeatActive = false;
302
26
  if (heartbeatTimer) {
@@ -305,64 +29,58 @@ export async function runTask(projectRoot, specFolderPath, taskNumber, config, a
305
29
  }
306
30
  logger?.clearStatus();
307
31
  };
308
- const logOutcome = (success, reason) => {
32
+ const logOutcome = (success, reason, extra) => {
309
33
  stopHeartbeat();
310
34
  const elapsedSeconds = Number(((Date.now() - startTime) / 1000).toFixed(1));
311
- logger?.info(formatTaskOutcomeLine(taskNumber, success, reason, elapsedSeconds, useSymbols));
35
+ logger?.info(formatTaskOutcomeLine(taskNumber, success, reason, elapsedSeconds, useSymbols, extra));
36
+ };
37
+ let measures = null;
38
+ const finish = (result) => measures ? measures.emitEnd().then(() => result) : Promise.resolve(result);
39
+ const fail = async (reason, marker, error, extra) => {
40
+ await measures?.emitEnd();
41
+ await writeDeadMarker(runDir, taskNumber, marker, projectRoot);
42
+ await recordDeadEvent(specFolderPath, taskNumber, reason);
43
+ logOutcome(false, reason, extra);
44
+ return { success: false, reason, error };
312
45
  };
313
- const approvedPath = path.join(runDir, 'approved');
314
46
  let approvedHash = '';
315
47
  try {
316
- approvedHash = (await fs.readFile(approvedPath, 'utf8')).trim();
48
+ approvedHash = (await fs.readFile(path.join(runDir, 'approved'), 'utf8')).trim();
317
49
  }
318
50
  catch {
319
- await fs.mkdir(deadDir, { recursive: true });
320
- await fs.writeFile(path.join(deadDir, `${taskNumber}.md`), '---\nreason: spec_conflict\n---\nSpec has not been approved (missing .run/approved).\n', 'utf8');
321
- await recordDeadEvent(specFolderPath, taskNumber, 'spec_conflict');
322
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, 'spec_conflict'));
323
- logOutcome(false, 'spec_conflict');
324
- return { success: false, reason: 'spec_conflict', error: 'Missing .run/approved' };
51
+ const marker = '---\nreason: spec_conflict\n---\nSpec has not been approved (missing .run/approved).\n';
52
+ return fail('spec_conflict', marker, 'Missing .run/approved');
325
53
  }
326
54
  const currentHash = await hashChangeFolder(specFolderPath);
327
55
  if (currentHash !== approvedHash) {
328
- await fs.mkdir(deadDir, { recursive: true });
329
- await fs.writeFile(path.join(deadDir, `${taskNumber}.md`), `---\nreason: spec_conflict\napproved_hash: "${approvedHash}"\ncurrent_hash: "${currentHash}"\n---\nChange folder modified after approval. Expected ${approvedHash}, computed ${currentHash}.\n`, 'utf8');
330
- await recordDeadEvent(specFolderPath, taskNumber, 'spec_conflict');
331
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, 'spec_conflict'));
332
- logOutcome(false, 'spec_conflict');
333
- return {
334
- success: false,
335
- reason: 'spec_conflict',
336
- error: `Folder hash mismatch: expected ${approvedHash}, got ${currentHash}`,
337
- };
56
+ const marker = `---\nreason: spec_conflict\napproved_hash: "${approvedHash}"\ncurrent_hash: "${currentHash}"\n---\nChange folder modified after approval. Expected ${approvedHash}, computed ${currentHash}.\n`;
57
+ const error = `Folder hash mismatch: expected ${approvedHash}, got ${currentHash}`;
58
+ return fail('spec_conflict', marker, error);
338
59
  }
339
60
  const taskPath = path.join(specFolderPath, 'tasks', `${taskNumber}.md`);
340
61
  let taskContent = '';
341
62
  try {
342
63
  taskContent = await fs.readFile(taskPath, 'utf8');
343
64
  }
344
- catch (err) {
345
- await fs.mkdir(deadDir, { recursive: true });
346
- await fs.writeFile(path.join(deadDir, `${taskNumber}.md`), `---\nreason: crashed\n---\nTask file not found: ${taskPath}\n`, 'utf8');
347
- await recordDeadEvent(specFolderPath, taskNumber, 'crashed');
348
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, 'crashed'));
349
- logOutcome(false, 'crashed');
350
- return { success: false, reason: 'crashed', error: 'Task file not found' };
65
+ catch {
66
+ const marker = `---\nreason: crashed\n---\nTask file not found: ${taskPath}\n`;
67
+ return fail('crashed', marker, 'Task file not found');
351
68
  }
352
69
  const taskData = parseTaskMd(taskContent);
353
- const lockResult = await acquireLock(runDir, taskNumber);
70
+ const regression = await guardScopeRegression(projectRoot, specFolderPath, taskNumber, config);
71
+ if (regression) {
72
+ logOutcome(false, 'regressed', regression.error);
73
+ return regression;
74
+ }
75
+ const lockResult = await acquireTaskLock(runDir, taskNumber);
354
76
  if (!lockResult.acquired) {
355
- // A lock collision means another process is actively running this task, not
356
- // that the task failed. It writes no dead marker, so it must not append a
357
- // dead event either; only a dead marker write may record a dead event.
358
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, 'already_running'));
359
77
  logOutcome(false, 'already_running');
360
78
  return { success: false, reason: 'already_running', error: 'Task is already running' };
361
79
  }
362
80
  if (heartbeatIntervalMs > 0) {
363
81
  const tickIntervalMs = interactive ? Math.min(heartbeatIntervalMs, 1000) : heartbeatIntervalMs;
364
82
  heartbeatTimer = setInterval(() => {
365
- computeTaskHeartbeatStats(specFolderPath, taskNumber, startTime)
83
+ computeTaskHeartbeatStats(specFolderPath, taskNumber, startTime, projectRoot)
366
84
  .then((stats) => {
367
85
  if (!heartbeatActive)
368
86
  return;
@@ -383,214 +101,47 @@ export async function runTask(projectRoot, specFolderPath, taskNumber, config, a
383
101
  heartbeatTimer.unref();
384
102
  }
385
103
  try {
386
- const spawnStartMs = startTime;
387
- const timeoutSeconds = config.timeouts.taskTimeoutSeconds;
388
- // The runner alone owns lifecycle events. `started` is emitted the moment
389
- // the child process exists via `onSpawn`, not after the adapter resolves.
390
- let startedRecorded = false;
391
- let startedPromise = null;
392
- const recordStarted = (pid) => {
393
- if (startedRecorded) {
394
- return startedPromise ?? Promise.resolve();
395
- }
396
- startedRecorded = true;
397
- startedPromise = recordLifecycleEvent(specFolderPath, taskNumber, {
398
- type: 'started',
399
- timestamp: new Date().toISOString(),
400
- data: { pid, timeoutSeconds },
401
- }, formatTaskStartedLine(taskNumber, taskData.title, pid, timeoutSeconds, useSymbols), logger);
402
- return startedPromise;
403
- };
404
- const spawnResult = await adapter.spawn({
104
+ const testGate = await captureTestGate(projectRoot, taskData.scope, taskData.testsModify);
105
+ const verifyCtx = { projectRoot, specFolderPath, taskNumber, taskData, config, logger };
106
+ const preSpawn = await runPreSpawnVerify(verifyCtx);
107
+ if (!preSpawn.ok)
108
+ return fail('verify_precondition', preSpawn.marker, preSpawn.error);
109
+ measures = createTaskMeasures(projectRoot, specFolderPath, taskNumber, taskData);
110
+ await measures.emitStart();
111
+ const spawnOutcome = await spawnTaskAgent({
405
112
  projectRoot,
406
113
  specFolderPath,
407
114
  taskNumber,
408
- taskTitle: taskData.title,
409
- verifyCommand: taskData.verify,
410
- scope: taskData.scope,
411
- entry: taskData.entry,
412
- skills: taskData.skills,
413
- tier: 'coding',
414
- timeoutSeconds,
115
+ taskData,
415
116
  config,
416
- onSpawn: (pid) => recordStarted(pid),
417
- });
418
- // Fallback: an adapter that never invokes onSpawn (or a spawn that fails
419
- // before the callback) still yields exactly one `started` event.
420
- await recordStarted(spawnResult.pid);
421
- const elapsedMs = spawnResult.elapsedMs ?? Date.now() - spawnStartMs;
422
- const elapsedSeconds = Number((elapsedMs / 1000).toFixed(1));
423
- await recordLifecycleEvent(specFolderPath, taskNumber, {
424
- type: 'exited',
425
- timestamp: new Date().toISOString(),
426
- data: {
427
- exitCode: spawnResult.exitCode,
428
- pid: spawnResult.pid,
429
- signal: spawnResult.signal ?? undefined,
430
- timedOut: spawnResult.timedOut,
431
- elapsedSeconds,
432
- },
433
- }, `task ${taskNumber} exited (code: ${spawnResult.exitCode}, elapsed: ${elapsedSeconds}s)`, logger, 'verbose');
434
- if (spawnResult.exitCode !== 0 || spawnResult.timedOut) {
435
- const failureReason = spawnResult.timedOut ? 'timeout' : 'crashed';
436
- await fs.mkdir(deadDir, { recursive: true });
437
- const deadMarkerLines = [
438
- '---',
439
- `reason: ${failureReason}`,
440
- `exit_code: ${spawnResult.exitCode}`,
441
- ];
442
- if (spawnResult.signal) {
443
- deadMarkerLines.push(`signal: ${spawnResult.signal}`);
444
- }
445
- deadMarkerLines.push('---');
446
- deadMarkerLines.push(`Agent ${spawnResult.timedOut ? 'timed out' : 'crashed'} with code ${spawnResult.exitCode}: ${spawnResult.error || ''}\n`);
447
- await fs.writeFile(path.join(deadDir, `${taskNumber}.md`), deadMarkerLines.join('\n'), 'utf8');
448
- await recordDeadEvent(specFolderPath, taskNumber, failureReason);
449
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, failureReason, failureReason === 'crashed' ? `code: ${spawnResult.exitCode}` : undefined));
450
- logOutcome(false, failureReason);
451
- return {
452
- success: false,
453
- reason: failureReason,
454
- error: spawnResult.error || `Agent exited with code ${spawnResult.exitCode}`,
455
- };
456
- }
457
- const resultPath = path.join(runDir, 'results', `${taskNumber}.md`);
458
- let hasResult = false;
459
- try {
460
- await fs.stat(resultPath);
461
- hasResult = true;
462
- }
463
- catch { }
464
- if (!hasResult) {
465
- const finalText = await extractFinalTextFromStream(specFolderPath, taskNumber);
466
- if (finalText) {
467
- await synthesizeResultFile(path.join(runDir, 'results'), taskNumber, finalText);
468
- await appendHarnessEvent(specFolderPath, taskNumber, {
469
- type: 'result_written',
470
- timestamp: new Date().toISOString(),
471
- data: { path: resultPath, synthesized: true },
472
- });
473
- logger?.verbose(`task ${taskNumber} result synthesized from agent message`);
474
- }
475
- else {
476
- await fs.mkdir(deadDir, { recursive: true });
477
- await fs.writeFile(path.join(deadDir, `${taskNumber}.md`), `---\nreason: no_result\n---\nAgent exited without writing result file at .run/results/${taskNumber}.md and produced no final text.\n`, 'utf8');
478
- await recordDeadEvent(specFolderPath, taskNumber, 'no_result');
479
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, 'no_result'));
480
- logOutcome(false, 'no_result');
481
- return {
482
- success: false,
483
- reason: 'no_result',
484
- error: `Agent exited without writing .run/results/${taskNumber}.md`,
485
- };
486
- }
487
- }
488
- await appendHarnessEvent(specFolderPath, taskNumber, {
489
- type: 'verify_ran',
490
- timestamp: new Date().toISOString(),
491
- data: { command: taskData.verify },
492
- });
493
- const verifyTimeoutMs = (config.timeouts.verifyTimeoutSeconds ?? 600) * 1000;
494
- let verifyTimedOut = false;
495
- const verifyPromise = new Promise((resolve, reject) => {
496
- const child = spawn(taskData.verify, {
497
- cwd: projectRoot,
498
- shell: true,
499
- detached: true,
500
- stdio: ['ignore', 'pipe', 'pipe'],
501
- });
502
- let timer = null;
503
- let killTimer = null;
504
- if (verifyTimeoutMs > 0) {
505
- timer = setTimeout(() => {
506
- verifyTimedOut = true;
507
- const childPid = child.pid;
508
- if (childPid) {
509
- try {
510
- process.kill(-childPid, 'SIGTERM');
511
- }
512
- catch {
513
- try {
514
- child.kill('SIGTERM');
515
- }
516
- catch { }
517
- }
518
- killTimer = setTimeout(() => {
519
- try {
520
- process.kill(-childPid, 'SIGKILL');
521
- }
522
- catch {
523
- try {
524
- child.kill('SIGKILL');
525
- }
526
- catch { }
527
- }
528
- }, 5000);
529
- }
530
- }, verifyTimeoutMs);
531
- }
532
- let stderr = '';
533
- let stdout = '';
534
- child.stderr?.on('data', (d) => {
535
- stderr += d.toString();
536
- });
537
- child.stdout?.on('data', (d) => {
538
- stdout += d.toString();
539
- });
540
- child.on('error', (err) => {
541
- if (timer)
542
- clearTimeout(timer);
543
- if (killTimer)
544
- clearTimeout(killTimer);
545
- reject(err);
546
- });
547
- child.on('close', (code) => {
548
- if (timer)
549
- clearTimeout(timer);
550
- if (killTimer)
551
- clearTimeout(killTimer);
552
- if (verifyTimedOut) {
553
- reject(new Error(`Verify command timed out after ${config.timeouts.verifyTimeoutSeconds ?? 600}s`));
554
- }
555
- else if (code !== 0) {
556
- reject(new Error(stderr || stdout || `Process exited with code ${code}`));
557
- }
558
- else {
559
- resolve();
560
- }
561
- });
117
+ adapter,
118
+ logger,
119
+ logOutcome,
562
120
  });
563
- try {
564
- await verifyPromise;
565
- }
566
- catch (verifyErr) {
567
- const msg = verifyErr instanceof Error ? verifyErr.message : String(verifyErr);
568
- await fs.mkdir(deadDir, { recursive: true });
569
- const deadLines = ['---', 'reason: verify_red'];
570
- if (verifyTimedOut) {
571
- deadLines.push('timed_out: true');
572
- }
573
- deadLines.push(`command: "${taskData.verify}"`);
574
- deadLines.push('---');
575
- deadLines.push(`Watcher independent verify ${verifyTimedOut ? 'timed out' : 'failed'}:\n${msg}\n`);
576
- await fs.writeFile(path.join(deadDir, `${taskNumber}.md`), deadLines.join('\n'), 'utf8');
577
- await recordDeadEvent(specFolderPath, taskNumber, 'verify_red');
578
- logger?.info(formatTaskOutcomeSummary(taskNumber, false, 'verify_red', verifyTimedOut ? 'timed_out: true' : undefined));
579
- logOutcome(false, 'verify_red');
580
- return {
581
- success: false,
582
- reason: 'verify_red',
583
- error: `Verify failed: ${msg}`,
584
- };
121
+ if (!spawnOutcome.ok)
122
+ return finish(spawnOutcome.result);
123
+ const undeclared = await findUndeclaredTestChanges(projectRoot, testGate.snapshot, testGate);
124
+ if (undeclared.length > 0) {
125
+ const marker = `---\nreason: undeclared_test_change\n---\nPreexisting test files were modified or deleted without both tests.modify: true and an authorizing scope entry:\n${undeclared.map((file) => `- ${file}`).join('\n')}\n`;
126
+ const error = `Undeclared test changes: ${undeclared.join(', ')}`;
127
+ return fail('undeclared_test_change', marker, error);
585
128
  }
586
- try {
587
- await fs.unlink(path.join(deadDir, `${taskNumber}.md`));
129
+ const ensured = await ensureTaskResult({ specFolderPath, taskNumber, logger, logOutcome });
130
+ if (!ensured.ok)
131
+ return finish(ensured.result);
132
+ const missingPath = await checkMissingVerifyPaths(projectRoot, taskData, fail);
133
+ if (missingPath)
134
+ return missingPath;
135
+ const verifyResult = await runVerificationGate(projectRoot, taskData.verify, config.timeouts.verifyTimeoutSeconds ?? 600, { specFolderPath, taskNumber });
136
+ if (!verifyResult.passed) {
137
+ return verifyRedFailure(taskData.verify, verifyResult, fail);
588
138
  }
589
- catch { }
590
- await fs.mkdir(doneDir, { recursive: true });
591
- await fs.writeFile(path.join(doneDir, taskNumber), `${new Date().toISOString()}\n`, 'utf8');
139
+ const gate = await runChangeVerifyGate(projectRoot, specFolderPath, config);
140
+ if (!gate.ok)
141
+ return fail('change_verify_red', gate.marker, gate.error, gate.extra);
142
+ await measures.emitEnd();
143
+ await writeDoneMarker(runDir, taskNumber, await buildDoneMetadata(projectRoot, taskData.scope));
592
144
  await recordDoneEvent(specFolderPath, taskNumber);
593
- logger?.info(formatTaskOutcomeSummary(taskNumber, true));
594
145
  logOutcome(true);
595
146
  await tickTaskCheckbox(specFolderPath, taskNumber);
596
147
  return { success: true };
@@ -598,7 +149,7 @@ export async function runTask(projectRoot, specFolderPath, taskNumber, config, a
598
149
  finally {
599
150
  stopHeartbeat();
600
151
  clearTaskHeartbeatStats(specFolderPath, taskNumber);
601
- await releaseLock(runDir, taskNumber);
152
+ await releaseTaskLock(runDir, taskNumber);
602
153
  }
603
154
  }
604
155
  //# sourceMappingURL=runner.js.map