@repo-os/repoos 0.5.74 → 0.5.76

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 (336) hide show
  1. package/README.md +12 -15
  2. package/dist/.build-info.json +2 -2
  3. package/dist/.build-stamp.json +1 -1
  4. package/dist/cli/api-route-parity.js +9 -0
  5. package/dist/cli/help.js +10 -3
  6. package/dist/cli/index.js +7 -1
  7. package/dist/cli/repoos-api.d.ts +1 -0
  8. package/dist/cli/repoos-api.js +1 -0
  9. package/dist/commands/check.d.ts +2 -0
  10. package/dist/commands/check.js +50 -5
  11. package/dist/commands/checks.js +96 -18
  12. package/dist/commands/control-api.d.ts +6 -0
  13. package/dist/commands/control-api.js +56 -6
  14. package/dist/commands/docs.js +2 -0
  15. package/dist/commands/gc.js +24 -26
  16. package/dist/commands/init.js +15 -15
  17. package/dist/commands/schedule.js +15 -1
  18. package/dist/commands/serve-banner.test.js +24 -1
  19. package/dist/commands/serve.d.ts +5 -0
  20. package/dist/commands/serve.js +20 -0
  21. package/dist/commands/status.d.ts +32 -3
  22. package/dist/commands/status.js +61 -16
  23. package/dist/commands/tasks.d.ts +1 -1
  24. package/dist/commands/tasks.js +4 -4
  25. package/dist/commands/ui-smoke.js +8 -7
  26. package/dist/commands/uninstall.d.ts +3 -0
  27. package/dist/commands/uninstall.js +84 -21
  28. package/dist/commands/upgrade.d.ts +1 -7
  29. package/dist/commands/upgrade.js +2 -19
  30. package/dist/core/active-task-card.d.ts +90 -0
  31. package/dist/core/active-task-card.js +187 -0
  32. package/dist/core/active-without-engineer-recovery.d.ts +34 -0
  33. package/dist/core/active-without-engineer-recovery.js +40 -0
  34. package/dist/core/agent-contract.js +2 -4
  35. package/dist/core/agent-run-tmpdir.d.ts +43 -0
  36. package/dist/core/agent-run-tmpdir.js +97 -0
  37. package/dist/core/attention.d.ts +2 -2
  38. package/dist/core/attention.js +1 -0
  39. package/dist/core/budget-runtime-state.d.ts +41 -0
  40. package/dist/core/budget-runtime-state.js +198 -0
  41. package/dist/core/check-plan.js +1 -1
  42. package/dist/core/check-results-store.d.ts +1 -0
  43. package/dist/core/check-results-store.js +1 -0
  44. package/dist/core/check-runner.d.ts +1 -0
  45. package/dist/core/check-runner.js +44 -37
  46. package/dist/core/check-skip.js +1 -1
  47. package/dist/core/check-store.d.ts +29 -1
  48. package/dist/core/check-store.js +167 -1
  49. package/dist/core/config.js +111 -34
  50. package/dist/core/cross-process-slots.js +61 -22
  51. package/dist/core/cto-idle-nudge.d.ts +13 -0
  52. package/dist/core/cto-idle-nudge.js +13 -5
  53. package/dist/core/done-task-cleanup.d.ts +6 -0
  54. package/dist/core/done-task-cleanup.js +53 -0
  55. package/dist/core/driver-brief.js +2 -0
  56. package/dist/core/engineer-crash-recovery.d.ts +32 -0
  57. package/dist/core/engineer-crash-recovery.js +112 -10
  58. package/dist/core/engineer-slot.d.ts +15 -0
  59. package/dist/core/engineer-slot.js +21 -0
  60. package/dist/core/git.d.ts +44 -2
  61. package/dist/core/git.js +338 -50
  62. package/dist/core/indexer.js +15 -4
  63. package/dist/core/install-layout.d.ts +11 -0
  64. package/dist/core/install-layout.js +50 -0
  65. package/dist/core/landable.d.ts +13 -5
  66. package/dist/core/landable.js +38 -5
  67. package/dist/core/launcher-runtime.d.ts +14 -0
  68. package/dist/core/launcher-runtime.js +129 -0
  69. package/dist/core/needs-input.js +2 -0
  70. package/dist/core/pipeline-view.d.ts +102 -0
  71. package/dist/core/pipeline-view.js +164 -0
  72. package/dist/core/pipeline-view.test.d.ts +1 -0
  73. package/dist/core/pipeline-view.test.js +147 -0
  74. package/dist/core/process-group.d.ts +11 -0
  75. package/dist/core/process-group.js +39 -0
  76. package/dist/core/queued-message-recovery.d.ts +65 -0
  77. package/dist/core/queued-message-recovery.js +62 -0
  78. package/dist/core/repoos-toml-runtime-diff.d.ts +1 -0
  79. package/dist/core/repoos-toml-runtime-diff.js +70 -0
  80. package/dist/core/report-paths.d.ts +29 -0
  81. package/dist/core/report-paths.js +60 -0
  82. package/dist/core/review-findings.js +14 -2
  83. package/dist/core/review-passes.d.ts +24 -5
  84. package/dist/core/review-passes.js +74 -29
  85. package/dist/core/schedule.d.ts +9 -0
  86. package/dist/core/schedule.js +20 -1
  87. package/dist/core/shot-fixtures.d.ts +1 -1
  88. package/dist/core/shot-fixtures.js +29 -0
  89. package/dist/core/task.d.ts +13 -2
  90. package/dist/core/task.js +41 -4
  91. package/dist/core/test-case-timings.d.ts +36 -0
  92. package/dist/core/test-case-timings.js +85 -0
  93. package/dist/core/types.d.ts +19 -0
  94. package/dist/core/watchdog-task-diff.d.ts +2 -0
  95. package/dist/core/watchdog-task-diff.js +113 -0
  96. package/dist/core/worktree-gc.d.ts +55 -13
  97. package/dist/core/worktree-gc.js +726 -94
  98. package/dist/server/__tests__/shot-capture-lock.test.d.ts +1 -0
  99. package/dist/server/__tests__/shot-capture-lock.test.js +18 -0
  100. package/dist/server/active-task-card.d.ts +24 -0
  101. package/dist/server/active-task-card.js +73 -0
  102. package/dist/server/active-without-engineer-recovery.d.ts +15 -0
  103. package/dist/server/active-without-engineer-recovery.js +148 -0
  104. package/dist/server/agents.d.ts +103 -2
  105. package/dist/server/agents.js +391 -38
  106. package/dist/server/attention-events.js +2 -1
  107. package/dist/server/attention-notify.d.ts +2 -0
  108. package/dist/server/attention-notify.js +15 -0
  109. package/dist/server/auto-engineering.d.ts +2 -1
  110. package/dist/server/auto-engineering.js +13 -8
  111. package/dist/server/branchless-release.d.ts +14 -0
  112. package/dist/server/branchless-release.js +96 -24
  113. package/dist/server/built-in-agent-runner.js +2 -0
  114. package/dist/server/cto-actions.d.ts +5 -0
  115. package/dist/server/cto-actions.js +5 -0
  116. package/dist/server/cto-monitor.d.ts +13 -0
  117. package/dist/server/cto-monitor.js +101 -34
  118. package/dist/server/cto.d.ts +4 -3
  119. package/dist/server/cto.js +8 -5
  120. package/dist/server/debug-tldr.js +5 -2
  121. package/dist/server/decision-digest.d.ts +6 -0
  122. package/dist/server/decision-digest.js +3 -1
  123. package/dist/server/done-hold-migration.d.ts +8 -0
  124. package/dist/server/done-hold-migration.js +69 -0
  125. package/dist/server/done.d.ts +1 -0
  126. package/dist/server/done.js +24 -3
  127. package/dist/server/driver-brief.d.ts +12 -0
  128. package/dist/server/driver-brief.js +7 -1
  129. package/dist/server/engineer-crash-recovery.js +15 -18
  130. package/dist/server/engineer-launch.js +22 -0
  131. package/dist/server/engineering-reports.d.ts +70 -0
  132. package/dist/server/engineering-reports.js +239 -0
  133. package/dist/server/freeform-runs.d.ts +2 -1
  134. package/dist/server/freeform-runs.js +16 -2
  135. package/dist/server/git-worker.d.ts +2 -0
  136. package/dist/server/git-worker.js +14 -2
  137. package/dist/server/handoff-status.d.ts +59 -0
  138. package/dist/server/handoff-status.js +226 -0
  139. package/dist/server/handoff.d.ts +10 -0
  140. package/dist/server/handoff.js +233 -14
  141. package/dist/server/integration-orchestrator.d.ts +18 -0
  142. package/dist/server/integration-orchestrator.js +139 -43
  143. package/dist/server/model-test.d.ts +3 -0
  144. package/dist/server/model-test.js +16 -1
  145. package/dist/server/provider-usage-limit-probe.js +6 -8
  146. package/dist/server/release-history.d.ts +46 -0
  147. package/dist/server/release-history.js +123 -0
  148. package/dist/server/release.js +158 -13
  149. package/dist/server/remote-validation.d.ts +17 -4
  150. package/dist/server/remote-validation.js +119 -27
  151. package/dist/server/report-layout-migration.d.ts +31 -0
  152. package/dist/server/report-layout-migration.js +182 -0
  153. package/dist/server/request-close-out.js +6 -3
  154. package/dist/server/review-automation.d.ts +1 -0
  155. package/dist/server/review-automation.js +3 -0
  156. package/dist/server/review-guard.js +4 -2
  157. package/dist/server/review-report-store.d.ts +23 -0
  158. package/dist/server/review-report-store.js +56 -0
  159. package/dist/server/review-tree-identity.js +49 -2
  160. package/dist/server/review.d.ts +63 -1
  161. package/dist/server/review.js +345 -104
  162. package/dist/server/routes/check-runs.d.ts +2 -0
  163. package/dist/server/routes/check-runs.js +40 -0
  164. package/dist/server/routes/config.js +16 -5
  165. package/dist/server/routes/decisions.js +1 -0
  166. package/dist/server/routes/dev.js +2 -0
  167. package/dist/server/routes/docs.js +3 -0
  168. package/dist/server/routes/driver.js +1 -0
  169. package/dist/server/routes/inputs.js +5 -1
  170. package/dist/server/routes/models.js +5 -1
  171. package/dist/server/routes/playground.js +5 -1
  172. package/dist/server/routes/release.js +3 -0
  173. package/dist/server/routes/stories.d.ts +3 -0
  174. package/dist/server/routes/stories.js +40 -1
  175. package/dist/server/routes/support.js +6 -1
  176. package/dist/server/routes/tasks.d.ts +10 -0
  177. package/dist/server/routes/tasks.js +116 -19
  178. package/dist/server/routes/ui.js +1 -1
  179. package/dist/server/server.js +206 -23
  180. package/dist/server/shot-capture.d.ts +2 -0
  181. package/dist/server/shot-capture.js +34 -1
  182. package/dist/server/skill-suggestions.js +2 -1
  183. package/dist/server/story-pm.js +15 -2
  184. package/dist/server/system.d.ts +79 -0
  185. package/dist/server/system.js +243 -1
  186. package/dist/server/task-check.d.ts +9 -0
  187. package/dist/server/task-check.js +24 -1
  188. package/dist/server/task-watchdog.d.ts +14 -0
  189. package/dist/server/task-watchdog.js +65 -8
  190. package/dist/server/ui-handoff-gate.js +10 -5
  191. package/dist/server/worktree-handoff-guard.js +7 -2
  192. package/dist/server/write.js +3 -13
  193. package/dist/ui/assets/ActivityIndicator-meIh-6Qi.js +1 -0
  194. package/dist/ui/assets/AgentModelControl-CUkgcahC.js +1 -0
  195. package/dist/ui/assets/AgentModelModal-et6vEhsU.js +1 -0
  196. package/dist/ui/assets/AgentsView-DBPauK5u.css +1 -0
  197. package/dist/ui/assets/AgentsView-DF4JpOuL.js +2 -0
  198. package/dist/ui/assets/{ChatAgentModelChip-CwDV90K2.js → ChatAgentModelChip-BzJzDKcR.js} +1 -1
  199. package/dist/ui/assets/ChecksView-C7N3Ypeq.js +0 -0
  200. package/dist/ui/assets/ChecksView-CfIhwy6Z.css +1 -0
  201. package/dist/ui/assets/{ConfirmDialog-Dwn2G-I8.js → ConfirmDialog-C-nDmuId.js} +1 -1
  202. package/dist/ui/assets/ContextView-BZdavSqS.js +4 -0
  203. package/dist/ui/assets/DashboardView-OFLi1McO.js +1 -0
  204. package/dist/ui/assets/{DashboardView-DJdeWV8s.css → DashboardView-jENeCIEX.css} +1 -1
  205. package/dist/ui/assets/DeleteConfirmDialog-CZ-PtFd3.js +1 -0
  206. package/dist/ui/assets/DeploymentsView-BvFWskO3.js +1 -0
  207. package/dist/ui/assets/{DevView-CYfAT-0x.js → DevView-DKXpK5Qm.js} +2 -2
  208. package/dist/ui/assets/{DiffView-BTDGsIts.js → DiffView-Br-vTJ0v.js} +2 -2
  209. package/dist/ui/assets/FailedTestsList-DoNaF-o9.js +1 -0
  210. package/dist/ui/assets/InputsView-KeayUEJY.js +1 -0
  211. package/dist/ui/assets/LoginView-CvXpXpGP.js +1 -0
  212. package/dist/ui/assets/PageSkeleton-CsTdMpw3.css +1 -0
  213. package/dist/ui/assets/PageSkeleton-DJRKj5JK.js +1 -0
  214. package/dist/ui/assets/{ReleasesView-BTN2vXUI.js → ReleasesView-9CdkP52G.js} +2 -2
  215. package/dist/ui/assets/SecretsView-BwDra-GT.js +1 -0
  216. package/dist/ui/assets/SettingsView-DNCRJx13.js +4 -0
  217. package/dist/ui/assets/StoriesView-DEihGJ88.css +1 -0
  218. package/dist/ui/assets/StoriesView-to9fS2F0.js +1 -0
  219. package/dist/ui/assets/{VoiceDictate-CES0G8Vq.js → VoiceDictate-CaVNQ8T-.js} +2 -2
  220. package/dist/ui/assets/WorkView-C7qnLKcz.css +1 -0
  221. package/dist/ui/assets/WorkView-D9GE8twS.js +2 -0
  222. package/dist/ui/assets/{abnfDiagram-VCTEODGH-DqUj4qFG.js → abnfDiagram-VCTEODGH-BI749mHF.js} +1 -1
  223. package/dist/ui/assets/{architectureDiagram-5GKGNRK7-DAHlI7NO.js → architectureDiagram-5GKGNRK7-CtGA7LVO.js} +1 -1
  224. package/dist/ui/assets/{blockDiagram-I7D4REHJ-BZ71-q2F.js → blockDiagram-I7D4REHJ-puRAhxem.js} +1 -1
  225. package/dist/ui/assets/{button-BskHmmtR.js → button-II9J4IUe.js} +1 -1
  226. package/dist/ui/assets/{c4Diagram-7LVT6UL2-CXbbODvo.js → c4Diagram-7LVT6UL2-C4CGYisP.js} +1 -1
  227. package/dist/ui/assets/channel-D_S1ZUW_.js +1 -0
  228. package/dist/ui/assets/check-setup-DSNmeJ0T.js +2 -0
  229. package/dist/ui/assets/{checkbox-BdCUqK2K.js → checkbox-4IcB0C9m.js} +1 -1
  230. package/dist/ui/assets/{chunk-2E4U76K2-RYa4g59L.js → chunk-2E4U76K2-DjnKVsYi.js} +1 -1
  231. package/dist/ui/assets/{chunk-4HAMMTFA-CXuZpZ_d.js → chunk-4HAMMTFA-CDnKKfj8.js} +1 -1
  232. package/dist/ui/assets/{chunk-75Z2AOVW-BP2GTRXO.js → chunk-75Z2AOVW-CKQ7DeM6.js} +1 -1
  233. package/dist/ui/assets/{chunk-CLGD4ZFX-DLzOmHqh.js → chunk-CLGD4ZFX-C4wu0WZN.js} +1 -1
  234. package/dist/ui/assets/{chunk-DU6HZSFF-DdjsSi6z.js → chunk-DU6HZSFF-DrJ5bmzy.js} +1 -1
  235. package/dist/ui/assets/{chunk-F27PBJKO-Dnn5wO3i.js → chunk-F27PBJKO-CzXjmHDd.js} +1 -1
  236. package/dist/ui/assets/{chunk-GMAD6QVW-DdG_nfFi.js → chunk-GMAD6QVW-CcWcSwCd.js} +1 -1
  237. package/dist/ui/assets/{chunk-GVQU2GXP-DMAbXLSv.js → chunk-GVQU2GXP-BaenLrCK.js} +1 -1
  238. package/dist/ui/assets/{chunk-IMKFNOWR-DHz_-TDB.js → chunk-IMKFNOWR-JyaOH2dq.js} +1 -1
  239. package/dist/ui/assets/{chunk-L3NEJ4N5-BwhWYbi6.js → chunk-L3NEJ4N5-D-Soe8Pq.js} +1 -1
  240. package/dist/ui/assets/{chunk-OSK3NFVY-CWlbubvG.js → chunk-OSK3NFVY-DyEqccWY.js} +1 -1
  241. package/dist/ui/assets/{chunk-P2QGCYS3-D9Muf9td.js → chunk-P2QGCYS3-PZxLXffD.js} +1 -1
  242. package/dist/ui/assets/{chunk-POPQ4Y6H-D3ODGb45.js → chunk-POPQ4Y6H-CLOE0hWn.js} +1 -1
  243. package/dist/ui/assets/{chunk-PWAF6VOD-D6LRyAPN.js → chunk-PWAF6VOD-092-eJK8.js} +1 -1
  244. package/dist/ui/assets/{chunk-SHT3W25Y-CXu4onhx.js → chunk-SHT3W25Y-CSc5sy8R.js} +1 -1
  245. package/dist/ui/assets/{chunk-SVP7TREG-7kV5LYQU.js → chunk-SVP7TREG-BLTmX5VJ.js} +1 -1
  246. package/dist/ui/assets/{chunk-TICWLB2K-ygSlNLtb.js → chunk-TICWLB2K-SzItQUhb.js} +1 -1
  247. package/dist/ui/assets/chunk-TLUHSLCS-DMnSH-ft.js +2 -0
  248. package/dist/ui/assets/classDiagram-ZZMXUADV-B7QHFk-U.js +1 -0
  249. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-B7QHFk-U.js +1 -0
  250. package/dist/ui/assets/{close-DyBUPuic.js → close-DcpwMOTE.js} +1 -1
  251. package/dist/ui/assets/{cynefinDiagram-5FMLGOSQ-DDFWjNjK.js → cynefinDiagram-5FMLGOSQ-1ilx8mKu.js} +1 -1
  252. package/dist/ui/assets/{dagre-GXQ25YYZ-CClbhBuT.js → dagre-GXQ25YYZ-C3A59Q6w.js} +1 -1
  253. package/dist/ui/assets/{diagram-S7CK7UJ4-BXdPXgUF.js → diagram-S7CK7UJ4-B-6B9kWN.js} +1 -1
  254. package/dist/ui/assets/{diagram-UQ7AKVKN-Cx3iFpM0.js → diagram-UQ7AKVKN-BqxmQJR8.js} +1 -1
  255. package/dist/ui/assets/{diagram-VSXAHHWV-szmYWA2M.js → diagram-VSXAHHWV-Ck9wWlUm.js} +1 -1
  256. package/dist/ui/assets/{diagram-VX7I27RA-CX2RE3DT.js → diagram-VX7I27RA-BQe2g3vh.js} +1 -1
  257. package/dist/ui/assets/{diagram-Z3DM3KII-CmMfHB9Q.js → diagram-Z3DM3KII-DD8365dG.js} +1 -1
  258. package/dist/ui/assets/docs-itn09t2R.js +1 -0
  259. package/dist/ui/assets/{ebnfDiagram-PWID7BFC-BO-2n4ZP.js → ebnfDiagram-PWID7BFC-Bz8cpJNy.js} +1 -1
  260. package/dist/ui/assets/{erDiagram-RLTQ6QDP-dCEqdV8F.js → erDiagram-RLTQ6QDP-Bc6u3S9N.js} +1 -1
  261. package/dist/ui/assets/flowDiagram-HODETNUW-Ba7ylFp4.js +1 -0
  262. package/dist/ui/assets/{ganttDiagram-EL5Y4UJY-BJb9E6tm.js → ganttDiagram-EL5Y4UJY-DVDVRjA0.js} +1 -1
  263. package/dist/ui/assets/{gitGraphDiagram-WWUBYQGX-B1CtsArh.js → gitGraphDiagram-WWUBYQGX-CFUXHZWf.js} +1 -1
  264. package/dist/ui/assets/index-DITWgaOj.css +1 -0
  265. package/dist/ui/assets/index-DqJOYNud.js +68 -0
  266. package/dist/ui/assets/{infoDiagram-27XIBGKW-a6qt1YhM.js → infoDiagram-27XIBGKW-C-7l9NCQ.js} +1 -1
  267. package/dist/ui/assets/{input-BxW7xGjP.js → input-DYSaV-Uv.js} +1 -1
  268. package/dist/ui/assets/{ishikawaDiagram-5VMMS53U-DU6MVFDK.js → ishikawaDiagram-5VMMS53U-Bjq-LdEc.js} +1 -1
  269. package/dist/ui/assets/{journeyDiagram-3NMN7TZE-oc0zPgCF.js → journeyDiagram-3NMN7TZE-o4M0lP2i.js} +1 -1
  270. package/dist/ui/assets/{kanban-definition-UXKFOSKX-BFCluyXI.js → kanban-definition-UXKFOSKX-BYqVEzsr.js} +1 -1
  271. package/dist/ui/assets/{line-C0dnI-L4.js → line-4TL08MsA.js} +1 -1
  272. package/dist/ui/assets/{mermaid-parser.core-CfrNQx8w.js → mermaid-parser.core-DrM_vPwv.js} +1 -1
  273. package/dist/ui/assets/mermaid.core-Dzz_-qU1.js +11 -0
  274. package/dist/ui/assets/{mindmap-definition-YA3MSWOX-DEEwX5b3.js → mindmap-definition-YA3MSWOX-CaKNZzR5.js} +1 -1
  275. package/dist/ui/assets/{pegDiagram-XKGWAZYB-P0QyFQvY.js → pegDiagram-XKGWAZYB-DbKJ-jrI.js} +1 -1
  276. package/dist/ui/assets/{pieDiagram-E7YTZNPT-DUingoVK.js → pieDiagram-E7YTZNPT-CPiwJysC.js} +1 -1
  277. package/dist/ui/assets/{quadrantDiagram-AXDQQJYC-5KZfHHFZ.js → quadrantDiagram-AXDQQJYC-q32X56Gx.js} +1 -1
  278. package/dist/ui/assets/{railroadDiagram-O6MQD6OU-D0sx6QJB.js → railroadDiagram-O6MQD6OU-DNMhXeke.js} +1 -1
  279. package/dist/ui/assets/repo-BuEVC7d2.js +59 -0
  280. package/dist/ui/assets/{requirementDiagram-BXWQKSXE-B4DIJgDV.js → requirementDiagram-BXWQKSXE-BW09ERRd.js} +1 -1
  281. package/dist/ui/assets/{sankeyDiagram-P5KCCOFB-Ds9sRhEp.js → sankeyDiagram-P5KCCOFB-BM5y8xIj.js} +1 -1
  282. package/dist/ui/assets/{sequenceDiagram-WJ2MYXX4-BsebZj2V.js → sequenceDiagram-WJ2MYXX4-QCl8JI9d.js} +1 -1
  283. package/dist/ui/assets/{stateDiagram-D77RDMKH-D4ndCrsI.js → stateDiagram-D77RDMKH-CURAhx8F.js} +1 -1
  284. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-CnyC3tkF.js +1 -0
  285. package/dist/ui/assets/{swimlanes-42K2YHIH-DUuSZaDY.js → swimlanes-42K2YHIH-CxCV3G9b.js} +1 -1
  286. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-R6ULRXhK.js +8 -0
  287. package/dist/ui/assets/{switch-QAs7KZBM.js → switch-fubkLBfv.js} +1 -1
  288. package/dist/ui/assets/{timeline-definition-24CTP7MA-UcuOAqHi.js → timeline-definition-24CTP7MA-_hEyz10W.js} +1 -1
  289. package/dist/ui/assets/{title-Ct1YpRGS.js → title-DrjQrrPh.js} +1 -1
  290. package/dist/ui/assets/{value-CnDjI3IE.js → value-UmIPBXR_.js} +1 -1
  291. package/dist/ui/assets/vendor-ui-BIC6pWFX.js +3 -0
  292. package/dist/ui/assets/{vennDiagram-4TSXK5OY-Doc_z7zd.js → vennDiagram-4TSXK5OY-CdB16vQ8.js} +1 -1
  293. package/dist/ui/assets/{viewport-BF2CEetx.js → viewport-vp1hmik7.js} +1 -1
  294. package/dist/ui/assets/{wardleyDiagram-VM6X3IG4-BbAt19tq.js → wardleyDiagram-VM6X3IG4-Bl7UPuNA.js} +1 -1
  295. package/dist/ui/assets/{xychartDiagram-S5SC5T6Z-CFT0no8b.js → xychartDiagram-S5SC5T6Z-BN1ho0Vx.js} +1 -1
  296. package/dist/ui/index.html +20 -22
  297. package/dist/ui/sw.js +2 -2
  298. package/package.json +3 -3
  299. package/dist/ui/assets/ActivityIndicator-4ufauHwi.js +0 -1
  300. package/dist/ui/assets/AgentModelControl-9-ZIzPrl.js +0 -1
  301. package/dist/ui/assets/AgentModelModal-Dgv9l_07.js +0 -1
  302. package/dist/ui/assets/AgentsView-Bl9Olksk.js +0 -2
  303. package/dist/ui/assets/AgentsView-SbjUmYp0.css +0 -1
  304. package/dist/ui/assets/ChecksView-DTrP7Uuz.js +0 -0
  305. package/dist/ui/assets/ChecksView-DVFC0J4t.css +0 -1
  306. package/dist/ui/assets/ContextView-CxfgyJ-y.js +0 -4
  307. package/dist/ui/assets/DashboardView-5rGQ9OEh.js +0 -1
  308. package/dist/ui/assets/DeleteConfirmDialog-Cy8bXm1R.js +0 -1
  309. package/dist/ui/assets/DependencyChip-CRG4bs5o.js +0 -1
  310. package/dist/ui/assets/DeploymentsView-BFOhkvLs.js +0 -1
  311. package/dist/ui/assets/FailedTestsList-xY10Qzc8.js +0 -1
  312. package/dist/ui/assets/InputsView-7HAgIHQh.js +0 -1
  313. package/dist/ui/assets/LoginView-BwP14kSS.js +0 -1
  314. package/dist/ui/assets/PageSkeleton-2lGeBsoi.css +0 -1
  315. package/dist/ui/assets/PageSkeleton-D7fVi3NJ.js +0 -1
  316. package/dist/ui/assets/SecretsView-CAFjCFQF.js +0 -1
  317. package/dist/ui/assets/SettingsView-B2WOxPud.js +0 -4
  318. package/dist/ui/assets/StoriesView-C-euuUSI.js +0 -1
  319. package/dist/ui/assets/StoriesView-CRo6XH_e.css +0 -1
  320. package/dist/ui/assets/WorkView-B1JytTp3.css +0 -1
  321. package/dist/ui/assets/WorkView-C9qAO66W.js +0 -2
  322. package/dist/ui/assets/channel-Cz_Tghq-.js +0 -1
  323. package/dist/ui/assets/check-setup-Bng0rbuw.js +0 -2
  324. package/dist/ui/assets/chunk-TLUHSLCS-Bj-PwaDc.js +0 -2
  325. package/dist/ui/assets/classDiagram-ZZMXUADV-DHAdi9dV.js +0 -1
  326. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-DHAdi9dV.js +0 -1
  327. package/dist/ui/assets/docs-eoM8eVGk.js +0 -1
  328. package/dist/ui/assets/flowDiagram-HODETNUW-CX9qpoV4.js +0 -1
  329. package/dist/ui/assets/index-Pr4f9cgO.js +0 -68
  330. package/dist/ui/assets/index-m6du4z4N.css +0 -1
  331. package/dist/ui/assets/mermaid.core-CKD0p_aW.js +0 -11
  332. package/dist/ui/assets/repo-B9GZ5YkR.js +0 -40
  333. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BHwEjBfW.js +0 -1
  334. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-BrUdO8ca.js +0 -8
  335. package/dist/ui/assets/ui-fJTOEtHH.js +0 -7
  336. package/dist/ui/assets/vendor-ui-BJqOnU3b.js +0 -3
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # RepoOS
2
2
 
3
- **The repo is the operating system.**
3
+ **The repo is the operating system. Your AI dev team, living in your repo, for CTOs and builders.**
4
4
 
5
5
  RepoOS is a lightweight, repo-native way to track work that lives as markdown
6
- files inside your monorepo. Tasks, specs, bugs, and feature requests are plain
6
+ files inside your repo. Tasks, specs, bugs, and feature requests are plain
7
7
  `.md` files with YAML frontmatter — versioned in git, readable by humans, and
8
8
  designed to be consumed directly by AI coding agents.
9
9
 
@@ -50,7 +50,8 @@ curl -fsSL https://repoos.org/install | bash
50
50
  ```
51
51
 
52
52
  It runs on Bun when available (recommended), otherwise requires Node.js >=
53
- 20.6.0. It installs to `~/.repoos` and links `repoos` into `~/.local/bin`.
53
+ 20.6.0. It installs to `~/.local/share/repoos` and links `repoos` into
54
+ `~/.local/bin`. Machine state stays in `~/.repoos`.
54
55
 
55
56
  ### Homebrew
56
57
 
@@ -76,22 +77,18 @@ bun add -g @repo-os/repoos
76
77
  pnpm add -g @repo-os/repoos
77
78
  ```
78
79
 
79
- ### mise
80
+ mise is not a recommended install method. See `docs/install-layout.md`.
80
81
 
81
- ```bash
82
- mise use --global npm:@repo-os/repoos
83
- ```
84
-
85
- This uses mise's built-in npm backend and records RepoOS in your global mise
86
- configuration. Make sure [mise shell activation](https://mise.jdx.dev/getting-started.html)
87
- is enabled so its `repoos` shim is on your PATH.
82
+ Bun installs `bun` into `~/.bun/bin`; add that directory to `PATH` before
83
+ `bun add -g`. pnpm on a clean account needs `SHELL` set and `pnpm setup`
84
+ before a global install.
88
85
 
89
86
  Use the same tool to update a package-manager install: `npm update -g
90
87
  @repo-os/repoos`, `bun update -g @repo-os/repoos`, `pnpm update -g
91
- @repo-os/repoos`, `mise upgrade npm:@repo-os/repoos`, or `brew update && brew
92
- upgrade repo-os/tap/repoos`. A standalone install updates with `repoos upgrade`
93
- and removes with `repoos uninstall`. When run from a recognised package-manager
94
- install, `repoos upgrade` prints the matching package-manager command instead.
88
+ @repo-os/repoos`, or `brew update && brew upgrade repo-os/tap/repoos`. A
89
+ standalone install updates with `repoos upgrade` and removes with
90
+ `repoos uninstall`. When run from a recognised package-manager install,
91
+ `repoos upgrade` prints the matching package-manager command instead.
95
92
 
96
93
  Then in any repo:
97
94
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "hash": "acb4fde7b3c6e297f938786a4607f68999d8c272283c2b7d27f1d821525ef5dd",
3
- "version": "0.5.74",
2
+ "hash": "ee6f28bc85995205fba9c8e23d6fc9802ccba3ff85045ffd94eaba4a635c603f",
3
+ "version": "0.5.76",
4
4
  "devUi": false
5
5
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "generatedAt": "2026-10-30T16:08:37.438Z"
2
+ "generatedAt": "2026-11-05T04:53:41.853Z"
3
3
  }
@@ -18,6 +18,8 @@ const CONTROL_API_MATCHERS = [
18
18
  re("POST", /^\/api\/tasks\/([^/]+)\/needs-input\/dismiss$/.source),
19
19
  re("POST", /^\/api\/tasks\/([^/]+)\/review\/again$/.source),
20
20
  re("GET", /^\/api\/tasks\/([^/]+)\/landable$/.source),
21
+ // Non-blocking handoff outcome for `repoos handoff-status` (#1028).
22
+ re("GET", /^\/api\/tasks\/([^/]+)\/handoff-status$/.source),
21
23
  re("POST", /^\/api\/tasks\/([^/]+)\/preview$/.source),
22
24
  re("POST", /^\/api\/tasks\/([^/]+)\/preview\/stop$/.source),
23
25
  // `repoos shot` single-entry capture through the browser-capture policy (#0874).
@@ -73,6 +75,11 @@ const FILE_CLI_MATCHERS = [
73
75
  ];
74
76
  /** UI-only, SSE/hub, auth, or internal routes — no CLI required. */
75
77
  const UI_ONLY_MATCHERS = [
78
+ // Task-card-only explicit cancellation of a stalled, registered local check.
79
+ re("POST", /^\/api\/tasks\/([^/]+)\/cancel-check$/.source),
80
+ // Read-only task engineering-report history used by the Dev tab.
81
+ re("GET", /^\/api\/tasks\/([^/]+)\/engineering-reports$/.source),
82
+ re("GET", /^\/api\/tasks\/([^/]+)\/engineering-reports\/([^/]+)$/.source),
76
83
  under("/api/auth/"),
77
84
  under("/api/hub/"),
78
85
  under("/api/telegram/"),
@@ -111,6 +118,7 @@ const UI_ONLY_MATCHERS = [
111
118
  exact("GET", "/api/attention"),
112
119
  exact("GET", "/api/decisions"),
113
120
  exact("GET", "/api/check-runs"),
121
+ exact("GET", "/api/check-run-test-cases"),
114
122
  exact("GET", "/api/local-check-slots"),
115
123
  re("POST", /^\/api\/local-check-slots\/(\d+)\/release\/(\d+)$/.source),
116
124
  exact("GET", "/api/resource-queues"),
@@ -118,6 +126,7 @@ const UI_ONLY_MATCHERS = [
118
126
  re("GET", /^\/api\/tasks\/([^/]+)\/integration-job$/.source),
119
127
  re("POST", /^\/api\/tasks\/([^/]+)\/worktree-handoff\/discard$/.source),
120
128
  re("GET", /^\/api\/tasks\/([^/]+)\/review$/.source),
129
+ re("GET", /^\/api\/tasks\/([^/]+)\/review\/passes\/([^/]+)$/.source),
121
130
  re("POST", /^\/api\/tasks\/([^/]+)\/review\/message$/.source),
122
131
  re("POST", /^\/api\/tasks\/([^/]+)\/pm\/message$/.source),
123
132
  re("POST", /^\/api\/tasks\/([^/]+)\/pm\/interrupt$/.source),
package/dist/cli/help.js CHANGED
@@ -157,7 +157,13 @@ const GROUPS = [
157
157
  {
158
158
  name: "landable",
159
159
  usage: "landable <id> [--json] [--port N]",
160
- desc: "Read-only landing pre-checks (verdict, lock, worktree, merge, scope, main) — exits non-zero when not landable (GET /api/tasks/:id/landable)",
160
+ desc: "Read-only checks before merging (verdict, lock, worktree, merge, scope, main) — exits non-zero when the task is not ready to merge (GET /api/tasks/:id/landable)",
161
+ flags: "--json · --port",
162
+ },
163
+ {
164
+ name: "handoff-status",
165
+ usage: "handoff-status <id> [--json] [--port N]",
166
+ desc: "Non-blocking state of the latest handoff attempt: not requested, running, passed, failed or deferred (GET /api/tasks/:id/handoff-status)",
161
167
  flags: "--json · --port",
162
168
  },
163
169
  {
@@ -304,8 +310,9 @@ const GROUPS = [
304
310
  },
305
311
  {
306
312
  name: "checks timings",
307
- usage: "checks timings",
308
- desc: "Show recent check durations and the slowest test files",
313
+ usage: "checks timings [--tests] [--run-id ID] [--recent-runs N] [--limit N] [--offset N] [--json]",
314
+ desc: "Recent check durations, slowest test files, and slow individual test cases",
315
+ flags: "--tests · --run-id ID · --recent-runs N · --limit N · --offset N · --json",
309
316
  },
310
317
  {
311
318
  name: "checks slots",
package/dist/cli/index.js CHANGED
@@ -27,7 +27,7 @@ import { cmdCertify } from "../commands/certify.js";
27
27
  import { cmdSupport } from "../commands/support.js";
28
28
  import { cmdService } from "../commands/service.js";
29
29
  import { cmdServers } from "../commands/servers.js";
30
- import { cmdAgentsRunning, cmdConfig, cmdDone, cmdLandable, cmdMessage, cmdSendBack, cmdOverride, cmdPause, cmdPreview, cmdDev, cmdReview, cmdVerify, cmdRunners, cmdStart, cmdSync, cmdStats, cmdDecisions, cmdApi, cmdIntegration, cmdAttention, cmdHold, cmdUnhold, } from "../commands/control-api.js";
30
+ import { cmdAgentsRunning, cmdConfig, cmdDone, cmdLandable, cmdHandoffStatus, cmdMessage, cmdSendBack, cmdOverride, cmdPause, cmdPreview, cmdDev, cmdReview, cmdVerify, cmdRunners, cmdStart, cmdSync, cmdStats, cmdDecisions, cmdApi, cmdIntegration, cmdAttention, cmdHold, cmdUnhold, } from "../commands/control-api.js";
31
31
  import { cmdWatch } from "../commands/watch.js";
32
32
  import { cmdDriver } from "../commands/driver.js";
33
33
  import { cmdBundle } from "../commands/bundle.js";
@@ -327,6 +327,12 @@ function main() {
327
327
  process.exitCode = code;
328
328
  });
329
329
  break;
330
+ case "handoff-status":
331
+ void cmdHandoffStatus(rest).then((code) => {
332
+ if (code !== 0)
333
+ process.exitCode = code;
334
+ });
335
+ break;
330
336
  case "override":
331
337
  void cmdOverride(rest).then((code) => {
332
338
  if (code !== 0)
@@ -43,6 +43,7 @@ export declare class RepoOsApi {
43
43
  fetchEventStream(): Promise<Response>;
44
44
  request(method: string, path: string, body?: unknown, opts?: {
45
45
  retryAuth?: boolean;
46
+ timeoutMs?: number;
46
47
  }): Promise<{
47
48
  status: number;
48
49
  body: ApiJson;
@@ -127,6 +127,7 @@ export class RepoOsApi {
127
127
  method,
128
128
  headers: this.buildHeaders(jsonBody),
129
129
  body: jsonBody ? JSON.stringify(body) : undefined,
130
+ signal: opts.timeoutMs && opts.timeoutMs > 0 ? AbortSignal.timeout(opts.timeoutMs) : undefined,
130
131
  });
131
132
  }
132
133
  catch (err) {
@@ -1,4 +1,5 @@
1
1
  import { type TestFileTiming } from "../core/test-file-timings.js";
2
+ import { type TestCaseTiming } from "../core/test-case-timings.js";
2
3
  import type { CheckContrastPair, CheckThemeScope, RepoOSConfig } from "../core/types.js";
3
4
  import { type CheckPlan, type CheckStep } from "../core/check-plan.js";
4
5
  import { type StepRunResult, type StepStatus } from "../core/check-runner.js";
@@ -275,6 +276,7 @@ interface StepContext {
275
276
  /** What a built-in `kind` handler returns. */
276
277
  interface BuiltinOutcome {
277
278
  testFileTimings?: TestFileTiming[];
279
+ testCaseTimings?: TestCaseTiming[];
278
280
  status: StepStatus;
279
281
  /** The command it resolved to (so the results block can name it). */
280
282
  command?: string;
@@ -33,6 +33,7 @@ import { cpus, totalmem } from "node:os";
33
33
  import { isAbsolute, join, relative, sep } from "node:path";
34
34
  import { c } from "../cli/colors.js";
35
35
  import { TestFileTimingCollector, testFileTimings, formatSlowestTestFiles, } from "../core/test-file-timings.js";
36
+ import { TestCaseTimingCollector, formatSlowestTestCases, mergeTestCaseTimings, pushTimingOutputChunk, } from "../core/test-case-timings.js";
36
37
  import { checkBuildForRoot } from "../core/build.js";
37
38
  import { findRepoRoot, loadConfig } from "../core/config.js";
38
39
  import { availableMemBytes } from "../core/sysmem.js";
@@ -1403,6 +1404,10 @@ async function stepTests(ctx) {
1403
1404
  : "skipped — test suite ran on the remote validation runner (REPOOS_SKIP_TESTS=1)");
1404
1405
  }
1405
1406
  const fileTimingCollector = new TestFileTimingCollector();
1407
+ const caseTimingCollector = new TestCaseTimingCollector();
1408
+ const onTimingChunk = (chunk) => {
1409
+ pushTimingOutputChunk(chunk, fileTimingCollector, caseTimingCollector);
1410
+ };
1406
1411
  const hasTestScript = Boolean(ctx.scriptPkg.scripts?.test);
1407
1412
  const hasTestFiles = ["test", "__tests__", "tests"].some((d) => existsSync(join(ctx.cwd, d)));
1408
1413
  if (!hasTestScript && !hasTestFiles)
@@ -1441,7 +1446,7 @@ async function stepTests(ctx) {
1441
1446
  console.log(c.dim(` · previously-failed test file(s) first · ${priorFiles.join(", ")}`));
1442
1447
  const pre = await runCommand({
1443
1448
  command: preflight,
1444
- onChunk: (chunk) => fileTimingCollector.push(chunk),
1449
+ onChunk: onTimingChunk,
1445
1450
  cwd: ctx.cwd,
1446
1451
  timeoutMs: 300_000,
1447
1452
  env,
@@ -1455,6 +1460,7 @@ async function stepTests(ctx) {
1455
1460
  status: pre.status === "timeout" ? "timeout" : "failed",
1456
1461
  command: preflight,
1457
1462
  testFileTimings: fileTimingCollector.values(),
1463
+ testCaseTimings: caseTimingCollector.values(),
1458
1464
  detail: `previously-failed test file(s) still fail — ${why}`,
1459
1465
  output: pre.output,
1460
1466
  };
@@ -1478,13 +1484,14 @@ async function stepTests(ctx) {
1478
1484
  timeoutMs,
1479
1485
  env,
1480
1486
  echo: ctx.echo,
1481
- onChunk: (chunk) => fileTimingCollector.push(chunk),
1487
+ onChunk: onTimingChunk,
1482
1488
  });
1483
1489
  if (res.status === "passed") {
1484
1490
  return {
1485
1491
  status: "passed",
1486
1492
  command,
1487
1493
  testFileTimings: fileTimingCollector.values(),
1494
+ testCaseTimings: caseTimingCollector.values(),
1488
1495
  detail: changedRef ? `scoped to changed vs ${changedRef} plus always-run suites` : undefined,
1489
1496
  output: res.output,
1490
1497
  };
@@ -1493,6 +1500,7 @@ async function stepTests(ctx) {
1493
1500
  return {
1494
1501
  status: "timeout",
1495
1502
  testFileTimings: fileTimingCollector.values(),
1503
+ testCaseTimings: caseTimingCollector.values(),
1496
1504
  command,
1497
1505
  detail: `timed out after ${timeoutLabel(timeoutMs)}`,
1498
1506
  output: res.output,
@@ -1504,6 +1512,7 @@ async function stepTests(ctx) {
1504
1512
  return {
1505
1513
  status: "failed",
1506
1514
  testFileTimings: fileTimingCollector.values(),
1515
+ testCaseTimings: caseTimingCollector.values(),
1507
1516
  command,
1508
1517
  detail: outputTail(res.output) ?? `Tests failed (exit ${res.exitCode})`,
1509
1518
  output: res.output,
@@ -1822,6 +1831,7 @@ export async function runCheckPlan(plan, opts) {
1822
1831
  required: step.required,
1823
1832
  isolationNote: outcome.isolationNote,
1824
1833
  testFileTimings: outcome.testFileTimings,
1834
+ testCaseTimings: outcome.testCaseTimings,
1825
1835
  });
1826
1836
  }
1827
1837
  return results;
@@ -2142,12 +2152,27 @@ export async function cmdCheck(argv = []) {
2142
2152
  console.log(c.red(`\n ✗ ${msg}\n`));
2143
2153
  const holders = inspectCrossProcessSlots(localCheckLockRoot(repoRoot, cfg.cacheDir ?? ".repoos"));
2144
2154
  for (const holder of holders) {
2145
- console.log(c.dim(` slot ${holder.slot}: pid ${holder.pid ?? "unknown"}, ${Math.round(holder.ageMs / 1000)}s${holder.dead ? " (dead; reclaiming)" : holder.wedged ? " (possibly wedged)" : ""}`));
2155
+ console.log(c.dim(` slot ${holder.slot}: pid ${holder.pid ?? "unknown"}, ${Math.round(holder.ageMs / 1000)}s${holder.dead ? " (process exited; reclaiming)" : holder.wedged ? ` (no recent heartbeat; last seen ${Math.round(holder.heartbeatAgeMs / 1000)}s ago)` : ""}`));
2146
2156
  }
2147
2157
  process.exit(1);
2148
2158
  }
2149
2159
  waitRecord = waits.finish();
2150
2160
  const runStartedAt = new Date();
2161
+ // Persist a provisional row before running steps. If this process is killed,
2162
+ // the durable history still shows an interrupted run instead of no run.
2163
+ const historyRunId = recordRunHistoryRow({
2164
+ root: checkStoreRoot,
2165
+ cacheDir: cfg.cacheDir,
2166
+ attribution: runContext,
2167
+ scope: changedRef ? `changed:${changedRef}` : "full",
2168
+ worktree: repoRoot,
2169
+ startedAt: runStartedAt.toISOString(),
2170
+ durationMs: 0,
2171
+ outcome: "cancelled",
2172
+ failedStep: "check",
2173
+ skippedSteps: [],
2174
+ detail: "Check was interrupted before completion.",
2175
+ });
2151
2176
  // Failed-first ordering (#0655): only interactive/CLI and pre-review runs
2152
2177
  // reorder. Close-out and release run their selected suite from a clean
2153
2178
  // slate, and the remote close-out gate never reaches this point. Attribution
@@ -2231,6 +2256,7 @@ export async function cmdCheck(argv = []) {
2231
2256
  skippedSteps: [],
2232
2257
  steps: completedSteps,
2233
2258
  detail: `check crashed before completing: ${e.message}`,
2259
+ updateId: historyRunId,
2234
2260
  });
2235
2261
  throw e;
2236
2262
  }
@@ -2290,9 +2316,17 @@ export async function cmdCheck(argv = []) {
2290
2316
  }
2291
2317
  }
2292
2318
  const fileTimings = results.flatMap((r) => r.testFileTimings ?? testFileTimings(r.output ?? ""));
2319
+ // Individual case history comes only from Vitest's structured reporter
2320
+ // events. Step output is intentionally bounded and must never be its source.
2321
+ const caseTimings = mergeTestCaseTimings(results.flatMap((r) => r.testCaseTimings ?? []));
2293
2322
  if (fileTimings.length) {
2294
2323
  heading("Slowest test files");
2295
2324
  console.log(formatSlowestTestFiles(fileTimings));
2325
+ console.log(c.dim(" File totals include hook time in that file; they are not the sum of individual cases below."));
2326
+ }
2327
+ if (caseTimings.length) {
2328
+ heading("Slowest test cases");
2329
+ console.log(formatSlowestTestCases(caseTimings));
2296
2330
  }
2297
2331
  // Persist the run for the Checks surface (#0447) before exiting. Fail-soft:
2298
2332
  // visibility only, never a reason to fail an otherwise-green gate.
@@ -2352,6 +2386,7 @@ export async function cmdCheck(argv = []) {
2352
2386
  durationMs: r.durationMs,
2353
2387
  output: r.output,
2354
2388
  testFileTimings: r.testFileTimings,
2389
+ testCaseTimings: r.testCaseTimings,
2355
2390
  detail: r.detail,
2356
2391
  required: r.required,
2357
2392
  })),
@@ -2377,6 +2412,7 @@ export async function cmdCheck(argv = []) {
2377
2412
  stepsDone: finalProgress?.stepsDone ?? null,
2378
2413
  stepsTotal: finalProgress?.stepsTotal ?? null,
2379
2414
  testFileTimings: fileTimings,
2415
+ testCaseTimings: caseTimings,
2380
2416
  testsDone: testProgress?.testsDone ?? null,
2381
2417
  testsTotal: testProgress?.testsTotal ?? null,
2382
2418
  detail: (() => {
@@ -2403,6 +2439,7 @@ export async function cmdCheck(argv = []) {
2403
2439
  failedTests: gatingFailures.flatMap((r) => extractFailedTests(r.output ?? "")),
2404
2440
  // Informational isolation label (#0655) — never part of the outcome.
2405
2441
  isolationNote: results.find((r) => r.isolationNote)?.isolationNote ?? null,
2442
+ updateId: historyRunId,
2406
2443
  });
2407
2444
  process.exit(gatingFailures.length > 0 ? 1 : 0);
2408
2445
  }
@@ -2438,7 +2475,8 @@ export function previousFailedTestsForRun(opts) {
2438
2475
  function recordRunHistoryRow(row) {
2439
2476
  try {
2440
2477
  const { taskId, phase } = row.attribution;
2441
- getCheckStore(row.root, row.cacheDir).record({
2478
+ const store = getCheckStore(row.root, row.cacheDir);
2479
+ const input = {
2442
2480
  taskId,
2443
2481
  phase,
2444
2482
  worktree: row.worktree,
@@ -2463,10 +2501,17 @@ function recordRunHistoryRow(row) {
2463
2501
  testsTotal: row.testsTotal,
2464
2502
  steps: row.steps,
2465
2503
  testFileTimings: row.testFileTimings,
2466
- });
2504
+ testCaseTimings: row.testCaseTimings,
2505
+ };
2506
+ if (row.updateId != null) {
2507
+ store.update(row.updateId, input);
2508
+ return row.updateId;
2509
+ }
2510
+ return store.record(input);
2467
2511
  }
2468
2512
  catch {
2469
2513
  /* never fail the gate on a history write */
2514
+ return null;
2470
2515
  }
2471
2516
  }
2472
2517
  /**
@@ -1,32 +1,110 @@
1
- import { getCheckStore } from "../core/check-store.js";
1
+ import { DEFAULT_TEST_CASE_LIST_LIMIT, getCheckStore, MAX_TEST_CASE_LIST_LIMIT, } from "../core/check-store.js";
2
2
  import { formatSlowestTestFiles } from "../core/test-file-timings.js";
3
+ import { formatSlowestTestCases } from "../core/test-case-timings.js";
3
4
  import { c } from "../cli/colors.js";
4
5
  import { loadConfig } from "../core/config.js";
5
6
  import { inspectCrossProcessSlots, listSlotWaiterPids, localCheckLockRoot, releaseLocalCheckSlot, } from "../core/cross-process-slots.js";
6
7
  import { currentQueueMarkers, readQueueMarkers } from "../core/local-queue-marker.js";
7
8
  import { mainCheckoutRoot } from "../core/git.js";
8
9
  import { heavySlotLimit } from "../core/resource-limits.js";
9
- export function cmdChecks(args) {
10
- if (args[0] === "timings") {
11
- const config = loadConfig();
12
- let root = config.root;
13
- try {
14
- root = mainCheckoutRoot(root);
10
+ function resolveChecksRoot() {
11
+ const config = loadConfig();
12
+ try {
13
+ return mainCheckoutRoot(config.root);
14
+ }
15
+ catch {
16
+ return config.root;
17
+ }
18
+ }
19
+ function parseTimingsFlags(args) {
20
+ let json = false;
21
+ let tests = false;
22
+ let runId;
23
+ let recentRuns = 10;
24
+ let limit = DEFAULT_TEST_CASE_LIST_LIMIT;
25
+ let offset = 0;
26
+ for (let i = 0; i < args.length; i++) {
27
+ const a = args[i];
28
+ if (a === "--json")
29
+ json = true;
30
+ else if (a === "--tests" || a === "tests")
31
+ tests = true;
32
+ else if (a === "--run-id" || a === "--run") {
33
+ const n = Number(args[++i]);
34
+ if (Number.isFinite(n) && n > 0)
35
+ runId = Math.floor(n);
36
+ }
37
+ else if (a === "--recent-runs" || a === "--recent") {
38
+ const n = Number(args[++i]);
39
+ if (Number.isFinite(n) && n > 0)
40
+ recentRuns = Math.min(100, Math.floor(n));
15
41
  }
16
- catch {
17
- /* standalone */
42
+ else if (a === "--limit") {
43
+ const n = Number(args[++i]);
44
+ if (Number.isFinite(n) && n > 0)
45
+ limit = Math.min(MAX_TEST_CASE_LIST_LIMIT, Math.floor(n));
18
46
  }
19
- for (const run of getCheckStore(root, config.cacheDir).list({ limit: 10 })) {
20
- console.log(`${run.startedAt} · ${run.phase} · ${run.machine ?? "local"} · ${run.scope} · ${((run.durationMs ?? 0) / 1000).toFixed(1)}s`);
21
- if (run.testFileTimings?.length) {
22
- console.log("Slowest test files (test + hook time):");
23
- console.log(formatSlowestTestFiles(run.testFileTimings));
24
- }
47
+ else if (a === "--offset") {
48
+ const n = Number(args[++i]);
49
+ if (Number.isFinite(n) && n >= 0)
50
+ offset = Math.floor(n);
25
51
  }
52
+ }
53
+ return { json, tests, runId, recentRuns, limit, offset };
54
+ }
55
+ function cmdChecksTimings(args) {
56
+ const config = loadConfig();
57
+ const root = resolveChecksRoot();
58
+ const flags = parseTimingsFlags(args);
59
+ const store = getCheckStore(root, config.cacheDir);
60
+ if (flags.tests) {
61
+ const result = store.listSlowTestCases({
62
+ runId: flags.runId,
63
+ recentRuns: flags.recentRuns,
64
+ limit: flags.limit,
65
+ offset: flags.offset,
66
+ });
67
+ if (flags.json) {
68
+ console.log(JSON.stringify({ ok: true, ...result }, null, 0));
69
+ return;
70
+ }
71
+ const scope = flags.runId != null
72
+ ? `run #${flags.runId}`
73
+ : `last ${result.recentRuns ?? flags.recentRuns} run(s)`;
74
+ console.log(`Slowest test cases (including beforeEach/afterEach hooks) · ${scope} · limit ${result.limit} offset ${result.offset}`);
75
+ if (!result.cases.length) {
76
+ console.log(" (no recorded cases — run repoos check after upgrading)");
77
+ return;
78
+ }
79
+ console.log(formatSlowestTestCases(result.cases.map(({ file, name, durationMs, result: outcome, retry, caseId }) => ({
80
+ file,
81
+ name,
82
+ caseId,
83
+ retry,
84
+ durationMs,
85
+ result: outcome,
86
+ })), result.limit));
87
+ if (result.hasMore) {
88
+ console.log(c.dim(` … more rows available (hasMore)`));
89
+ }
90
+ return;
91
+ }
92
+ for (const run of store.list({ limit: 10 })) {
93
+ console.log(`${run.startedAt} · ${run.phase} · ${run.machine ?? "local"} · ${run.scope} · ${((run.durationMs ?? 0) / 1000).toFixed(1)}s · run #${run.id}`);
94
+ if (run.testFileTimings?.length) {
95
+ console.log("Slowest test files (test + hook time in file):");
96
+ console.log(formatSlowestTestFiles(run.testFileTimings));
97
+ }
98
+ }
99
+ console.log(c.dim("\nIndividual cases: repoos checks timings --tests [--run-id ID] [--recent-runs N] [--limit N] [--offset N] [--json]"));
100
+ }
101
+ export function cmdChecks(args) {
102
+ if (args[0] === "timings") {
103
+ cmdChecksTimings(args.slice(1));
26
104
  return;
27
105
  }
28
106
  if (args[0] !== "slots") {
29
- console.error("Usage: repoos checks timings | slots [--release SLOT --confirm PID]");
107
+ console.error("Usage: repoos checks timings [--tests] [--run-id ID] [--recent-runs N] [--limit N] [--offset N] [--json] | slots [--release SLOT --confirm PID]");
30
108
  process.exitCode = 2;
31
109
  return;
32
110
  }
@@ -54,7 +132,7 @@ export function cmdChecks(args) {
54
132
  const holder = inspectCrossProcessSlots(root, heavySlotLimit(config), config.localChecks?.staleAfterMs).find((item) => item.slot === slot);
55
133
  if (!holder?.pid)
56
134
  throw new Error(`slot ${slot} is free`);
57
- console.log(`Releasing slot ${slot}, held by task #${String(holder.meta?.taskId ?? "unknown")} check, PID ${holder.pid}${holder.dead ? ", dead" : holder.wedged ? ", wedged" : ", alive"}.`);
135
+ console.log(`Releasing slot ${slot}, held by task #${String(holder.meta?.taskId ?? "unknown")} check, PID ${holder.pid}${holder.dead ? ", process exited" : holder.wedged ? `, no recent heartbeat (last seen ${Math.round(holder.heartbeatAgeMs / 1000)}s ago)` : ", alive"}.`);
58
136
  releaseLocalCheckSlot(root, slot, pid, config.localChecks?.staleAfterMs);
59
137
  console.log(c.green(" ✔ Slot released."));
60
138
  }
@@ -70,7 +148,7 @@ export function cmdChecks(args) {
70
148
  ? `#${String(holder.meta.taskId)} check`
71
149
  : "unattributed check";
72
150
  console.log(holder.pid
73
- ? `slot ${holder.slot}: ${task}, pid ${holder.pid}, ${holder.dead ? "dead, reclaiming" : holder.wedged ? "wedged" : "alive"}, held ${Math.round(holder.ageMs / 1000)}s, heartbeat ${Math.round(holder.heartbeatAgeMs / 1000)}s ago`
151
+ ? `slot ${holder.slot}: ${task}, pid ${holder.pid}, ${holder.dead ? "process exited, reclaiming" : holder.wedged ? `no recent heartbeat (last seen ${Math.round(holder.heartbeatAgeMs / 1000)}s ago)` : "alive"}, held ${Math.round(holder.ageMs / 1000)}s, heartbeat ${Math.round(holder.heartbeatAgeMs / 1000)}s ago`
74
152
  : `slot ${holder.slot}: free`);
75
153
  }
76
154
  const queue = currentQueueMarkers(readQueueMarkers(boardRoot, cacheDir).filter((entry) => entry.kind === "local-check"), listSlotWaiterPids(root));
@@ -83,6 +83,12 @@ interface StatsGitJobView {
83
83
  ageMs?: number;
84
84
  }
85
85
  export declare function printSystemSummary(system: StatsSystemView): void;
86
+ /**
87
+ * `repoos handoff-status <id>` (#1028): print the latest handoff attempt's
88
+ * state immediately. Never waits for, starts, or alters a handoff — safe to
89
+ * call from an engineer that is unsure whether its request reached the server.
90
+ */
91
+ export declare function cmdHandoffStatus(args: string[]): Promise<number>;
86
92
  /**
87
93
  * `repoos landable <id>` (#0867): print the read-only landing pre-checks and
88
94
  * exit 0 only when every check passes. Never edits, commits or moves status.
@@ -179,9 +179,9 @@ export async function cmdHold(args) {
179
179
  return 1;
180
180
  }
181
181
  const api = new RepoOsApi({ port: opts.port });
182
- // #0960 input validation (mirrors the API guard): a hold needs a reason so it
183
- // is visible on the board, and `--until` must be a real date or it would
184
- // never auto-release and become a permanent hold.
182
+ // #0960: the CLI still requires `--reason`. The HTTP hold route accepts a
183
+ // missing reason (#1033). `--until` must be a real date or it would never
184
+ // auto-release and become a permanent hold.
185
185
  if (!opts.reason || !opts.reason.trim()) {
186
186
  printErr("hold requires a --reason (free text documenting why the task is parked)");
187
187
  return 1;
@@ -738,7 +738,7 @@ export async function cmdDone(args) {
738
738
  console.log(`${result.status >= 200 && result.status < 300 ? c.green(" ✓ ") : c.yellow(" · ")}${message} (HTTP ${result.status})`);
739
739
  return (result.status >= 200 && result.status < 300) || result.status === 409 ? 0 : 1;
740
740
  }
741
- const started = await api.request("POST", `/api/tasks/${id}/done`, { commitDirty });
741
+ const started = await api.request("POST", `/api/tasks/${id}/done`, { commitDirty }, { timeoutMs: 0 });
742
742
  if (started.status === 409 && started.body.needsCommit) {
743
743
  throw new RepoOsApiError(started.body.error ?? "close-out blocked on dirty tree", 409, started.body);
744
744
  }
@@ -1506,6 +1506,56 @@ function landableIcon(status) {
1506
1506
  return c.yellow("!");
1507
1507
  return c.red("✗");
1508
1508
  }
1509
+ /**
1510
+ * `repoos handoff-status <id>` (#1028): print the latest handoff attempt's
1511
+ * state immediately. Never waits for, starts, or alters a handoff — safe to
1512
+ * call from an engineer that is unsure whether its request reached the server.
1513
+ */
1514
+ export async function cmdHandoffStatus(args) {
1515
+ const { rest, opts, error } = parseCommonFlags(args);
1516
+ if (error) {
1517
+ printErr(error);
1518
+ return 1;
1519
+ }
1520
+ const id = rest[0];
1521
+ if (!id) {
1522
+ printErr("Usage: repoos handoff-status <id> [--json] [--port N]");
1523
+ return 1;
1524
+ }
1525
+ const api = new RepoOsApi({ port: opts.port });
1526
+ try {
1527
+ await ensureServer(api);
1528
+ const status = (await api.requestOk("GET", `/api/tasks/${id}/handoff-status`));
1529
+ if (opts.json) {
1530
+ printJson(status);
1531
+ return 0;
1532
+ }
1533
+ const label = status.state === "passed"
1534
+ ? c.green("passed")
1535
+ : status.state === "failed"
1536
+ ? c.red("failed")
1537
+ : status.state === "running"
1538
+ ? c.yellow("running")
1539
+ : status.state === "deferred"
1540
+ ? c.yellow("deferred")
1541
+ : c.dim("not requested");
1542
+ console.log(` ${c.bold(`#${id}`)} handoff: ${label}`);
1543
+ if (status.step)
1544
+ console.log(` step: ${status.step}`);
1545
+ if (status.reason)
1546
+ console.log(` reason: ${status.reason}`);
1547
+ if (status.updatedAt)
1548
+ console.log(` at: ${status.updatedAt}`);
1549
+ if (status.state === "not_requested") {
1550
+ console.log(c.dim(` no handoff has been requested for this task (request it with \`repoos mv ${id} review\`)`));
1551
+ }
1552
+ return 0;
1553
+ }
1554
+ catch (e) {
1555
+ printErr(e.message);
1556
+ return 1;
1557
+ }
1558
+ }
1509
1559
  /**
1510
1560
  * `repoos landable <id>` (#0867): print the read-only landing pre-checks and
1511
1561
  * exit 0 only when every check passes. Never edits, commits or moves status.
@@ -1529,8 +1579,8 @@ export async function cmdLandable(args) {
1529
1579
  printJson(result);
1530
1580
  else {
1531
1581
  const verdict = result.landable
1532
- ? c.green(`#${id} is landable`)
1533
- : c.red(`#${id} is not landable yet`);
1582
+ ? c.green(`#${id} is ready to merge`)
1583
+ : c.red(`#${id} is not ready to merge yet`);
1534
1584
  console.log(` ${verdict}`);
1535
1585
  for (const check of result.checks) {
1536
1586
  console.log(` ${landableIcon(check.status)} ${c.bold(check.label)} — ${check.detail}`);
@@ -5,6 +5,7 @@ import { readFileSync } from "node:fs";
5
5
  import { createDocument, createFreeformDocument, docFreeformPrompt, parseGeneratedDocument, } from "../core/docs.js";
6
6
  import { loadConfig } from "../core/config.js";
7
7
  import { c } from "../cli/colors.js";
8
+ import { repoAgentRunTmpOpts } from "../core/agent-run-tmpdir.js";
8
9
  import { resolvePmAgent, runPrompt, recordOneShotSession } from "../server/agents.js";
9
10
  import { currentDocsDir, importDocsInto, scaffoldDocsInto } from "./docs-io.js";
10
11
  /** `repoos new-doc "<description>"` or `repoos new-doc --path docs/foo.md --content-file x.md` */
@@ -34,6 +35,7 @@ export async function cmdNewDoc(args) {
34
35
  const docResult = await createFreeformDocument(config, description, async (desc) => {
35
36
  const result = await runPrompt(pm, docFreeformPrompt(desc), {
36
37
  cwd: config.root,
38
+ ...repoAgentRunTmpOpts(config),
37
39
  });
38
40
  // Freeform doc authoring is real PM spend that belongs to no task (0311).
39
41
  recordOneShotSession(config.root, pm, result, { sessionType: "pm", taskId: null });