@repo-os/repoos 0.5.45

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 (362) hide show
  1. package/LICENSE.md +110 -0
  2. package/README.md +272 -0
  3. package/dist/.build-info.json +4 -0
  4. package/dist/.build-stamp.json +3 -0
  5. package/dist/cli/colors.d.ts +13 -0
  6. package/dist/cli/colors.js +37 -0
  7. package/dist/cli/index.d.ts +2 -0
  8. package/dist/cli/index.js +221 -0
  9. package/dist/commands/check.d.ts +170 -0
  10. package/dist/commands/check.js +1227 -0
  11. package/dist/commands/docs.d.ts +2 -0
  12. package/dist/commands/docs.js +70 -0
  13. package/dist/commands/gc.d.ts +1 -0
  14. package/dist/commands/gc.js +57 -0
  15. package/dist/commands/init.d.ts +9 -0
  16. package/dist/commands/init.js +699 -0
  17. package/dist/commands/screenshots.d.ts +7 -0
  18. package/dist/commands/screenshots.js +77 -0
  19. package/dist/commands/serve.d.ts +55 -0
  20. package/dist/commands/serve.js +204 -0
  21. package/dist/commands/status.d.ts +140 -0
  22. package/dist/commands/status.js +569 -0
  23. package/dist/commands/stop.d.ts +1 -0
  24. package/dist/commands/stop.js +59 -0
  25. package/dist/commands/tasks.d.ts +47 -0
  26. package/dist/commands/tasks.js +334 -0
  27. package/dist/commands/tunnel.d.ts +1 -0
  28. package/dist/commands/tunnel.js +1271 -0
  29. package/dist/commands/ui-harness.d.ts +53 -0
  30. package/dist/commands/ui-harness.js +62 -0
  31. package/dist/commands/ui-smoke.d.ts +6 -0
  32. package/dist/commands/ui-smoke.js +220 -0
  33. package/dist/commands/upgrade.d.ts +15 -0
  34. package/dist/commands/upgrade.js +188 -0
  35. package/dist/core/auth-store.d.ts +81 -0
  36. package/dist/core/auth-store.js +530 -0
  37. package/dist/core/auth.d.ts +75 -0
  38. package/dist/core/auth.js +124 -0
  39. package/dist/core/bootstrap.d.ts +41 -0
  40. package/dist/core/bootstrap.js +236 -0
  41. package/dist/core/build.d.ts +92 -0
  42. package/dist/core/build.js +249 -0
  43. package/dist/core/canary.d.ts +10 -0
  44. package/dist/core/canary.js +14 -0
  45. package/dist/core/check-failure-summary.d.ts +10 -0
  46. package/dist/core/check-failure-summary.js +34 -0
  47. package/dist/core/config.d.ts +160 -0
  48. package/dist/core/config.js +1288 -0
  49. package/dist/core/context-pack.d.ts +74 -0
  50. package/dist/core/context-pack.js +778 -0
  51. package/dist/core/db.d.ts +236 -0
  52. package/dist/core/db.js +747 -0
  53. package/dist/core/detect.d.ts +69 -0
  54. package/dist/core/detect.js +251 -0
  55. package/dist/core/docs.d.ts +76 -0
  56. package/dist/core/docs.js +225 -0
  57. package/dist/core/frontmatter.d.ts +29 -0
  58. package/dist/core/frontmatter.js +215 -0
  59. package/dist/core/git.d.ts +505 -0
  60. package/dist/core/git.js +1453 -0
  61. package/dist/core/indexer.d.ts +33 -0
  62. package/dist/core/indexer.js +282 -0
  63. package/dist/core/input.d.ts +66 -0
  64. package/dist/core/input.js +222 -0
  65. package/dist/core/logger.d.ts +70 -0
  66. package/dist/core/logger.js +138 -0
  67. package/dist/core/models.d.ts +45 -0
  68. package/dist/core/models.js +291 -0
  69. package/dist/core/net-probe.d.ts +4 -0
  70. package/dist/core/net-probe.js +20 -0
  71. package/dist/core/providers/deepinfra.d.ts +23 -0
  72. package/dist/core/providers/deepinfra.js +44 -0
  73. package/dist/core/providers/index.d.ts +24 -0
  74. package/dist/core/providers/index.js +59 -0
  75. package/dist/core/providers/openrouter.d.ts +28 -0
  76. package/dist/core/providers/openrouter.js +82 -0
  77. package/dist/core/providers/spend.d.ts +86 -0
  78. package/dist/core/providers/spend.js +286 -0
  79. package/dist/core/providers/types.d.ts +56 -0
  80. package/dist/core/providers/types.js +39 -0
  81. package/dist/core/repoos.d.ts +59 -0
  82. package/dist/core/repoos.js +221 -0
  83. package/dist/core/runtime.d.ts +35 -0
  84. package/dist/core/runtime.js +167 -0
  85. package/dist/core/skills-registry.d.ts +39 -0
  86. package/dist/core/skills-registry.js +148 -0
  87. package/dist/core/skills-registry.test.d.ts +1 -0
  88. package/dist/core/skills-registry.test.js +52 -0
  89. package/dist/core/sysmem.d.ts +7 -0
  90. package/dist/core/sysmem.js +55 -0
  91. package/dist/core/tailscale.d.ts +2 -0
  92. package/dist/core/tailscale.js +19 -0
  93. package/dist/core/task.d.ts +53 -0
  94. package/dist/core/task.js +310 -0
  95. package/dist/core/toml-line.d.ts +20 -0
  96. package/dist/core/toml-line.js +52 -0
  97. package/dist/core/toml-validate.d.ts +44 -0
  98. package/dist/core/toml-validate.js +335 -0
  99. package/dist/core/tunnel-assistant.d.ts +30 -0
  100. package/dist/core/tunnel-assistant.js +65 -0
  101. package/dist/core/tunnel-registry.d.ts +96 -0
  102. package/dist/core/tunnel-registry.js +267 -0
  103. package/dist/core/tunnel-registry.test.d.ts +1 -0
  104. package/dist/core/tunnel-registry.test.js +309 -0
  105. package/dist/core/tunnel.d.ts +103 -0
  106. package/dist/core/tunnel.js +320 -0
  107. package/dist/core/types.d.ts +811 -0
  108. package/dist/core/types.js +27 -0
  109. package/dist/core/worktree-gc.d.ts +57 -0
  110. package/dist/core/worktree-gc.js +194 -0
  111. package/dist/server/__tests__/integration-job.test.d.ts +1 -0
  112. package/dist/server/__tests__/integration-job.test.js +129 -0
  113. package/dist/server/agents.d.ts +1020 -0
  114. package/dist/server/agents.js +4070 -0
  115. package/dist/server/attachments.d.ts +51 -0
  116. package/dist/server/attachments.js +130 -0
  117. package/dist/server/auto-engineering.d.ts +45 -0
  118. package/dist/server/auto-engineering.js +275 -0
  119. package/dist/server/branchless-release.d.ts +22 -0
  120. package/dist/server/branchless-release.js +67 -0
  121. package/dist/server/built-in-agents.d.ts +305 -0
  122. package/dist/server/built-in-agents.js +1838 -0
  123. package/dist/server/cto-monitor.d.ts +35 -0
  124. package/dist/server/cto-monitor.js +281 -0
  125. package/dist/server/cto.d.ts +125 -0
  126. package/dist/server/cto.js +590 -0
  127. package/dist/server/deployments.d.ts +119 -0
  128. package/dist/server/deployments.js +325 -0
  129. package/dist/server/diff-snapshot.d.ts +20 -0
  130. package/dist/server/diff-snapshot.js +73 -0
  131. package/dist/server/done.d.ts +160 -0
  132. package/dist/server/done.js +488 -0
  133. package/dist/server/freeform.d.ts +55 -0
  134. package/dist/server/freeform.js +179 -0
  135. package/dist/server/handoff.d.ts +99 -0
  136. package/dist/server/handoff.js +575 -0
  137. package/dist/server/hetzner.d.ts +45 -0
  138. package/dist/server/hetzner.js +117 -0
  139. package/dist/server/icons.d.ts +8 -0
  140. package/dist/server/icons.js +195 -0
  141. package/dist/server/integration-job.d.ts +75 -0
  142. package/dist/server/integration-job.js +144 -0
  143. package/dist/server/integration-orchestrator.d.ts +211 -0
  144. package/dist/server/integration-orchestrator.js +1299 -0
  145. package/dist/server/integration-status.d.ts +48 -0
  146. package/dist/server/integration-status.js +71 -0
  147. package/dist/server/live-index.d.ts +295 -0
  148. package/dist/server/live-index.js +452 -0
  149. package/dist/server/model-test.d.ts +20 -0
  150. package/dist/server/model-test.js +100 -0
  151. package/dist/server/ntfy.d.ts +57 -0
  152. package/dist/server/ntfy.js +112 -0
  153. package/dist/server/pm-attachments.d.ts +35 -0
  154. package/dist/server/pm-attachments.js +181 -0
  155. package/dist/server/pm-runs.d.ts +58 -0
  156. package/dist/server/pm-runs.js +80 -0
  157. package/dist/server/preview.d.ts +174 -0
  158. package/dist/server/preview.js +641 -0
  159. package/dist/server/release.d.ts +88 -0
  160. package/dist/server/release.js +449 -0
  161. package/dist/server/reload.d.ts +194 -0
  162. package/dist/server/reload.js +586 -0
  163. package/dist/server/remote-validation.d.ts +132 -0
  164. package/dist/server/remote-validation.js +478 -0
  165. package/dist/server/repo-lock.d.ts +36 -0
  166. package/dist/server/repo-lock.js +141 -0
  167. package/dist/server/review-guard.d.ts +14 -0
  168. package/dist/server/review-guard.js +159 -0
  169. package/dist/server/review.d.ts +243 -0
  170. package/dist/server/review.js +1211 -0
  171. package/dist/server/routes/agents.d.ts +6 -0
  172. package/dist/server/routes/agents.js +28 -0
  173. package/dist/server/routes/auth.d.ts +60 -0
  174. package/dist/server/routes/auth.js +755 -0
  175. package/dist/server/routes/config.d.ts +20 -0
  176. package/dist/server/routes/config.js +347 -0
  177. package/dist/server/routes/debugger.d.ts +33 -0
  178. package/dist/server/routes/debugger.js +360 -0
  179. package/dist/server/routes/deployments.d.ts +3 -0
  180. package/dist/server/routes/deployments.js +16 -0
  181. package/dist/server/routes/docs.d.ts +8 -0
  182. package/dist/server/routes/docs.js +135 -0
  183. package/dist/server/routes/helpers.d.ts +21 -0
  184. package/dist/server/routes/helpers.js +171 -0
  185. package/dist/server/routes/index.d.ts +19 -0
  186. package/dist/server/routes/index.js +18 -0
  187. package/dist/server/routes/info.d.ts +17 -0
  188. package/dist/server/routes/info.js +177 -0
  189. package/dist/server/routes/inputs.d.ts +7 -0
  190. package/dist/server/routes/inputs.js +125 -0
  191. package/dist/server/routes/model-providers.d.ts +27 -0
  192. package/dist/server/routes/model-providers.js +94 -0
  193. package/dist/server/routes/models.d.ts +3 -0
  194. package/dist/server/routes/models.js +36 -0
  195. package/dist/server/routes/notify.d.ts +2 -0
  196. package/dist/server/routes/notify.js +17 -0
  197. package/dist/server/routes/playground.d.ts +29 -0
  198. package/dist/server/routes/playground.js +81 -0
  199. package/dist/server/routes/release.d.ts +20 -0
  200. package/dist/server/routes/release.js +86 -0
  201. package/dist/server/routes/router.d.ts +12 -0
  202. package/dist/server/routes/router.js +32 -0
  203. package/dist/server/routes/skill-registry.d.ts +5 -0
  204. package/dist/server/routes/skill-registry.js +51 -0
  205. package/dist/server/routes/tasks.d.ts +58 -0
  206. package/dist/server/routes/tasks.js +1442 -0
  207. package/dist/server/routes/transcribe.d.ts +2 -0
  208. package/dist/server/routes/transcribe.js +124 -0
  209. package/dist/server/routes/types.d.ts +68 -0
  210. package/dist/server/routes/types.js +1 -0
  211. package/dist/server/routes/ui.d.ts +5 -0
  212. package/dist/server/routes/ui.js +81 -0
  213. package/dist/server/routes/utils.d.ts +3 -0
  214. package/dist/server/routes/utils.js +23 -0
  215. package/dist/server/serve-reaper.d.ts +135 -0
  216. package/dist/server/serve-reaper.js +491 -0
  217. package/dist/server/server.d.ts +49 -0
  218. package/dist/server/server.js +2171 -0
  219. package/dist/server/supervisor.d.ts +89 -0
  220. package/dist/server/supervisor.js +231 -0
  221. package/dist/server/system.d.ts +198 -0
  222. package/dist/server/system.js +480 -0
  223. package/dist/server/task-check.d.ts +45 -0
  224. package/dist/server/task-check.js +71 -0
  225. package/dist/server/task-transitions.d.ts +51 -0
  226. package/dist/server/task-transitions.js +78 -0
  227. package/dist/server/task-watchdog.d.ts +158 -0
  228. package/dist/server/task-watchdog.js +681 -0
  229. package/dist/server/test-run.d.ts +28 -0
  230. package/dist/server/test-run.js +81 -0
  231. package/dist/server/watcher.d.ts +21 -0
  232. package/dist/server/watcher.js +194 -0
  233. package/dist/server/write.d.ts +94 -0
  234. package/dist/server/write.js +345 -0
  235. package/dist/ui/assets/AgentsView-CF4wRvHh.css +1 -0
  236. package/dist/ui/assets/AgentsView-D-myL-kA.js +1 -0
  237. package/dist/ui/assets/ContextView-D3TC-RSp.css +1 -0
  238. package/dist/ui/assets/ContextView-DsOqAdyE.js +4 -0
  239. package/dist/ui/assets/DashboardView-BOhsIJqO.js +1 -0
  240. package/dist/ui/assets/DashboardView-Ck9o0RP2.css +1 -0
  241. package/dist/ui/assets/DeploymentsView--iIUVfEH.css +1 -0
  242. package/dist/ui/assets/DeploymentsView-DXu_FYR2.js +1 -0
  243. package/dist/ui/assets/InputsView-24HVbVPk.js +1 -0
  244. package/dist/ui/assets/InputsView-BLb7GHtx.css +1 -0
  245. package/dist/ui/assets/LoginView-6QlGg6cx.css +1 -0
  246. package/dist/ui/assets/LoginView-BqupI0Lt.js +1 -0
  247. package/dist/ui/assets/ReleasesView-BEG1A0YH.css +1 -0
  248. package/dist/ui/assets/ReleasesView-CAgMuxpe.js +3 -0
  249. package/dist/ui/assets/SettingsView-CA-NYSMK.css +1 -0
  250. package/dist/ui/assets/SettingsView-O3iZSnjg.js +3 -0
  251. package/dist/ui/assets/WorkView-D8Tl6qwy.js +1 -0
  252. package/dist/ui/assets/WorkView-DMYL2s3W.css +1 -0
  253. package/dist/ui/assets/abnfDiagram-VCTEODGH-J5lkSnEE.js +1 -0
  254. package/dist/ui/assets/arc-BHZnmhhM.js +1 -0
  255. package/dist/ui/assets/architecture-7GRP2DOG-pLdFt-xS.js +1 -0
  256. package/dist/ui/assets/architectureDiagram-5GKGNRK7-C3k89uKX.js +36 -0
  257. package/dist/ui/assets/array-BifhSqXX.js +1 -0
  258. package/dist/ui/assets/blockDiagram-I7D4REHJ-AWNoBzop.js +129 -0
  259. package/dist/ui/assets/button-lbikqSph.js +1 -0
  260. package/dist/ui/assets/c4Diagram-7LVT6UL2-DKG1D5gd.js +38 -0
  261. package/dist/ui/assets/channel-gA4qBv3A.js +1 -0
  262. package/dist/ui/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  263. package/dist/ui/assets/chunk-4HAMMTFA-D1YR8lF_.js +62 -0
  264. package/dist/ui/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  265. package/dist/ui/assets/chunk-75Z2AOVW-5GuBxfsL.js +2 -0
  266. package/dist/ui/assets/chunk-DU6HZSFF-DfdNNqwa.js +127 -0
  267. package/dist/ui/assets/chunk-F27PBJKO-BPZzinQ4.js +1 -0
  268. package/dist/ui/assets/chunk-FOHPRMQF-l2z4K2jD.js +161 -0
  269. package/dist/ui/assets/chunk-GMAD6QVW-DGWvSKj5.js +72 -0
  270. package/dist/ui/assets/chunk-GVQU2GXP-D6Aw75wJ.js +1 -0
  271. package/dist/ui/assets/chunk-IMKFNOWR-B8mMBKCW.js +231 -0
  272. package/dist/ui/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  273. package/dist/ui/assets/chunk-L3NEJ4N5-D5OJuXYE.js +1 -0
  274. package/dist/ui/assets/chunk-OSK3NFVY-B7r9w2UW.js +10 -0
  275. package/dist/ui/assets/chunk-P2QGCYS3-C74X4AQX.js +1 -0
  276. package/dist/ui/assets/chunk-POPQ4Y6H-C5_u1gUS.js +1 -0
  277. package/dist/ui/assets/chunk-PWAF6VOD-DfoTLtxn.js +1 -0
  278. package/dist/ui/assets/chunk-SHT3W25Y-D40m2eqz.js +168 -0
  279. package/dist/ui/assets/chunk-SVP7TREG-euxi0Kap.js +88 -0
  280. package/dist/ui/assets/chunk-TICWLB2K-fkdxngzN.js +206 -0
  281. package/dist/ui/assets/chunk-XXDRQBXY-DFBUG-OT.js +1 -0
  282. package/dist/ui/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  283. package/dist/ui/assets/classDiagram-ZZMXUADV-BzW8bq2P.js +1 -0
  284. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-BzW8bq2P.js +1 -0
  285. package/dist/ui/assets/cose-bilkent-JH36ORCC-BTcgMon1.js +1 -0
  286. package/dist/ui/assets/cynefin-OW5HDTMX-B5m_COsS.js +1 -0
  287. package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-C-AG6CGe.js +62 -0
  288. package/dist/ui/assets/cytoscape.esm-FBntH-9t.js +321 -0
  289. package/dist/ui/assets/dagre-GXQ25YYZ-DDfDnp8L.js +4 -0
  290. package/dist/ui/assets/dagre-PrKaheQc.js +1 -0
  291. package/dist/ui/assets/defaultLocale-BFoDCU3G.js +1 -0
  292. package/dist/ui/assets/diagram-S7CK7UJ4-DjQZAlEY.js +30 -0
  293. package/dist/ui/assets/diagram-UQ7AKVKN-DAZ9yp1B.js +41 -0
  294. package/dist/ui/assets/diagram-VSXAHHWV-BWepUKJD.js +3 -0
  295. package/dist/ui/assets/diagram-VX7I27RA-EcV1J81b.js +24 -0
  296. package/dist/ui/assets/diagram-Z3DM3KII-Dbz7XU_K.js +24 -0
  297. package/dist/ui/assets/dist-DTg6UBE_.js +1 -0
  298. package/dist/ui/assets/ebnfDiagram-PWID7BFC-BUyQw8Mm.js +1 -0
  299. package/dist/ui/assets/erDiagram-RLTQ6QDP-WVf8ukKt.js +99 -0
  300. package/dist/ui/assets/eventmodeling-NTZA5JFV-DHqyLOAn.js +1 -0
  301. package/dist/ui/assets/flowDiagram-HODETNUW-CYk_ze5K.js +1 -0
  302. package/dist/ui/assets/ganttDiagram-EL5Y4UJY-rB4MZuB-.js +292 -0
  303. package/dist/ui/assets/gitGraph-4MIJSDKK-BOTWM8dY.js +1 -0
  304. package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-eYscuhtP.js +106 -0
  305. package/dist/ui/assets/graphlib-DS17s2tU.js +1 -0
  306. package/dist/ui/assets/index-BACBfnga.css +1 -0
  307. package/dist/ui/assets/index-BOQ-ust6.js +26 -0
  308. package/dist/ui/assets/info-A6RAGUB7-_67wOORe.js +1 -0
  309. package/dist/ui/assets/infoDiagram-27XIBGKW-XVXbddTA.js +2 -0
  310. package/dist/ui/assets/init-C-OQMol4.js +1 -0
  311. package/dist/ui/assets/ishikawaDiagram-5VMMS53U-ClLNiEru.js +70 -0
  312. package/dist/ui/assets/journeyDiagram-3NMN7TZE-NRawjR6i.js +139 -0
  313. package/dist/ui/assets/kanban-definition-UXKFOSKX-BgSzBfIx.js +89 -0
  314. package/dist/ui/assets/katex-DolUETbr.js +257 -0
  315. package/dist/ui/assets/line-KAyfuul4.js +1 -0
  316. package/dist/ui/assets/linear-cCCPOpu7.js +1 -0
  317. package/dist/ui/assets/mermaid-parser.core-CgXZk1iN.js +7 -0
  318. package/dist/ui/assets/mermaid.core-BUUkChHW.js +44 -0
  319. package/dist/ui/assets/mindmap-definition-YA3MSWOX-Cpn7vW4r.js +96 -0
  320. package/dist/ui/assets/ordinal-BDEzSJ7C.js +1 -0
  321. package/dist/ui/assets/packet-AYTQ26CC-0lZwM-d6.js +1 -0
  322. package/dist/ui/assets/path-COt_16Va.js +1 -0
  323. package/dist/ui/assets/pegDiagram-XKGWAZYB-impy0inn.js +1 -0
  324. package/dist/ui/assets/pie-WAS4IAKB-CqfdGHYg.js +1 -0
  325. package/dist/ui/assets/pieDiagram-E7YTZNPT-CxjL4I1h.js +39 -0
  326. package/dist/ui/assets/quadrantDiagram-AXDQQJYC-Cjd1QMIe.js +7 -0
  327. package/dist/ui/assets/radar-RG4KPBEZ-CRkQIwiv.js +1 -0
  328. package/dist/ui/assets/railroad-74A4TZTK-i67XSWTB.js +1 -0
  329. package/dist/ui/assets/railroad-abnf-HS5TGJTU-Cv9m5aS3.js +1 -0
  330. package/dist/ui/assets/railroad-ebnf-LZEXJU2U-C5ZIn-Jh.js +1 -0
  331. package/dist/ui/assets/railroad-peg-WCYAUIDC-CGra9Oq-.js +1 -0
  332. package/dist/ui/assets/railroadDiagram-O6MQD6OU-_pK0qyaY.js +1 -0
  333. package/dist/ui/assets/releases-B0WNV-SY.js +1 -0
  334. package/dist/ui/assets/repoos-cto-square.webp +0 -0
  335. package/dist/ui/assets/repoos-helpful-pm-square.webp +0 -0
  336. package/dist/ui/assets/repoos-orchestrator-square.webp +0 -0
  337. package/dist/ui/assets/repoos-performance-agent-square.webp +0 -0
  338. package/dist/ui/assets/repoos-ross-from-friends-square.webp +0 -0
  339. package/dist/ui/assets/repoos-tech-debt-agent-square.webp +0 -0
  340. package/dist/ui/assets/requirementDiagram-BXWQKSXE-CRrFX-yw.js +84 -0
  341. package/dist/ui/assets/rough.esm-By172zw-.js +1 -0
  342. package/dist/ui/assets/sankeyDiagram-P5KCCOFB-X_xFRj9E.js +40 -0
  343. package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-Byb49lKf.js +162 -0
  344. package/dist/ui/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  345. package/dist/ui/assets/src-BH-TyZbA.js +1 -0
  346. package/dist/ui/assets/stateDiagram-D77RDMKH-CzaPrqYF.js +1 -0
  347. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BCXckz7K.js +1 -0
  348. package/dist/ui/assets/swimlanes-42K2YHIH-Cx_1lnqr.js +1 -0
  349. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-54qsKi6A.js +8 -0
  350. package/dist/ui/assets/timeline-definition-24CTP7MA-B1IbZPQ-.js +120 -0
  351. package/dist/ui/assets/treeView-Q6P3EWNA-DFWhVE3d.js +1 -0
  352. package/dist/ui/assets/treemap-WGGIJYW6-BmbYPThn.js +1 -0
  353. package/dist/ui/assets/vendor-ui-DPm7zLxi.js +3 -0
  354. package/dist/ui/assets/vendor-vue-CobgyEJp.js +1 -0
  355. package/dist/ui/assets/vennDiagram-4TSXK5OY-Ae2AtRpt.js +34 -0
  356. package/dist/ui/assets/wardley-WFR3VGLG-BtD4X4tL.js +1 -0
  357. package/dist/ui/assets/wardleyDiagram-VM6X3IG4-B3YN2fTd.js +78 -0
  358. package/dist/ui/assets/xychartDiagram-S5SC5T6Z-CIzJfMKA.js +7 -0
  359. package/dist/ui/favicon.svg +11 -0
  360. package/dist/ui/index.html +49 -0
  361. package/dist/ui/sw.js +48 -0
  362. package/package.json +91 -0
@@ -0,0 +1,569 @@
1
+ /**
2
+ * `repoos status` — one-screen health/orientation snapshot for the
3
+ * repo-as-OS (#0324). Think `git status`: server, build freshness, board,
4
+ * worktrees, tunnel, git — collapsed into one screen so "what is off right
5
+ * now?" never requires knowing which of five commands to run.
6
+ *
7
+ * Must work with the server STOPPED: the serve lockfile, the build marker,
8
+ * `work/*.md` (via buildIndex), and git are read directly. When the server IS
9
+ * up, the picture is enriched from `/api/health` and `/api/tunnel/readiness`
10
+ * — but those calls are best-effort with tight timeouts, never required, and
11
+ * can never make this command hang.
12
+ *
13
+ * `--json` prints the same snapshot machine-readably (shape documented in
14
+ * docs/architecture.md, "repoos status"). Zero new runtime dependencies.
15
+ */
16
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
17
+ import { basename, join } from "node:path";
18
+ import { execFileSync } from "node:child_process";
19
+ import { boardRoot, loadConfig, resolveServePort } from "../core/config.js";
20
+ import { buildIndex } from "../core/indexer.js";
21
+ import { checkBuildForRoot, readBuildStamp } from "../core/build.js";
22
+ import { readTunnelConfig } from "../core/tunnel.js";
23
+ import { readRegistry, reconcileIdentity, syncFromRepo, unionApps, } from "../core/tunnel-registry.js";
24
+ import { currentBranch, runGit } from "../core/git.js";
25
+ import { countWorktrees, sweepStaleWorktrees } from "../core/worktree-gc.js";
26
+ import { isOrphanServeCommand, isPortListening } from "../server/serve-reaper.js";
27
+ import { STATUSES } from "../core/types.js";
28
+ import { c } from "../cli/colors.js";
29
+ /** EPERM means "alive but not ours" — still alive. */
30
+ function pidAlive(pid) {
31
+ try {
32
+ process.kill(pid, 0);
33
+ }
34
+ catch (e) {
35
+ return e.code === "EPERM";
36
+ }
37
+ // kill -0 only proves SOME process owns the PID — after OS PID recycling it
38
+ // may be an unrelated process that has nothing to do with this repo's
39
+ // server. Verify the command line has the repoos serve shape (the same
40
+ // matcher ServeReaper's orphan sweep uses) before trusting it. If `ps`
41
+ // itself fails, keep the existence verdict: collectStatus independently
42
+ // cross-checks the port before believing "running".
43
+ if (process.platform === "win32")
44
+ return true;
45
+ try {
46
+ const cmdline = execFileSync("ps", ["-p", String(pid), "-o", "command="], {
47
+ encoding: "utf8",
48
+ timeout: 2000,
49
+ stdio: ["ignore", "pipe", "ignore"],
50
+ }).trim();
51
+ if (!cmdline)
52
+ return false; // gone between kill(0) and ps
53
+ return isOrphanServeCommand(cmdline);
54
+ }
55
+ catch {
56
+ return true;
57
+ }
58
+ }
59
+ /** startedAt as a comparable number (missing/unparsable sorts oldest). */
60
+ function lockStartedMs(l) {
61
+ const t = Date.parse(l.startedAt ?? "");
62
+ return Number.isFinite(t) ? t : 0;
63
+ }
64
+ /**
65
+ * Read every `.repoos/serve[-<port>].lock`. Locks are scoped per port (see
66
+ * ServeReaper), so there can legitimately be more than one; they are ordered
67
+ * live-first, then newest-first by `startedAt`, so the primary is the one
68
+ * that matters. Exported for tests.
69
+ */
70
+ export function readServeLocks(root, cacheDir) {
71
+ let files;
72
+ try {
73
+ files = readdirSync(join(root, cacheDir)).filter((f) => /^serve(?:-\d+)?\.lock$/.test(f));
74
+ }
75
+ catch {
76
+ return [];
77
+ }
78
+ const out = [];
79
+ for (const file of files) {
80
+ try {
81
+ const raw = JSON.parse(readFileSync(join(root, cacheDir, file), "utf8"));
82
+ const pid = typeof raw.pid === "number" && Number.isInteger(raw.pid) ? raw.pid : 0;
83
+ const alive = pid > 0 && pid !== process.pid && pidAlive(pid);
84
+ out.push({
85
+ file,
86
+ pid,
87
+ port: typeof raw.port === "number" ? raw.port : null,
88
+ host: typeof raw.host === "string" ? raw.host : null,
89
+ startedAt: typeof raw.startedAt === "string" ? raw.startedAt : null,
90
+ alive,
91
+ });
92
+ }
93
+ catch {
94
+ /* corrupt lockfile — ignore; `repoos serve`'s reaper will clean it up */
95
+ }
96
+ }
97
+ out.sort((a, b) => Number(b.alive) - Number(a.alive) || lockStartedMs(b) - lockStartedMs(a));
98
+ return out;
99
+ }
100
+ async function probeHealth(port, root, timeoutMs) {
101
+ const miss = {
102
+ state: "unreachable",
103
+ root: null,
104
+ version: null,
105
+ serverStartedAt: null,
106
+ };
107
+ try {
108
+ const res = await fetch(`http://127.0.0.1:${port}/api/health`, {
109
+ signal: AbortSignal.timeout(timeoutMs),
110
+ });
111
+ if (!res.ok)
112
+ return miss;
113
+ const body = (await res.json());
114
+ if (body.ok !== true || typeof body.root !== "string")
115
+ return miss;
116
+ return {
117
+ state: body.root === root ? "ok" : "foreign",
118
+ root: body.root,
119
+ version: typeof body.version === "string" ? body.version : null,
120
+ serverStartedAt: typeof body.serverStartedAt === "string" ? body.serverStartedAt : null,
121
+ };
122
+ }
123
+ catch {
124
+ return miss;
125
+ }
126
+ }
127
+ /** pgrep for a running cloudflared tunnel process — same shape tunnel status uses. */
128
+ function tunnelProcessRunning() {
129
+ try {
130
+ return (execFileSync("pgrep", ["-f", "cloudflared.*tunnel.*run"], {
131
+ encoding: "utf8",
132
+ timeout: 2000,
133
+ stdio: ["ignore", "pipe", "ignore"],
134
+ }).trim() !== "");
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ /** launchd/systemd service state for cloudflared — same shape tunnel status uses. */
141
+ function tunnelServiceRunning() {
142
+ try {
143
+ if (process.platform === "darwin") {
144
+ const out = execFileSync("launchctl", ["list"], {
145
+ encoding: "utf8",
146
+ timeout: 2000,
147
+ stdio: ["ignore", "pipe", "ignore"],
148
+ });
149
+ return out
150
+ .split("\n")
151
+ .some((line) => line.includes("com.cloudflare.cloudflared") && /^\s*\d+\s+/.test(line));
152
+ }
153
+ if (process.platform === "linux") {
154
+ return (execFileSync("systemctl", ["is-active", "cloudflared"], {
155
+ encoding: "utf8",
156
+ timeout: 2000,
157
+ stdio: ["ignore", "pipe", "ignore"],
158
+ }).trim() === "active");
159
+ }
160
+ }
161
+ catch {
162
+ /* service manager unavailable */
163
+ }
164
+ return false;
165
+ }
166
+ function readVersionFromMarker(root) {
167
+ try {
168
+ const info = JSON.parse(readFileSync(join(root, "dist", ".build-info.json"), "utf8"));
169
+ return typeof info.version === "string" && info.version ? info.version : null;
170
+ }
171
+ catch {
172
+ return null;
173
+ }
174
+ }
175
+ /**
176
+ * Build the full snapshot. Everything is fail-soft: a missing lockfile, a dead
177
+ * server, an unreadable marker, or absent git degrade the matching section —
178
+ * never crash the command.
179
+ */
180
+ export async function collectStatus(config, opts = {}) {
181
+ const now = opts.now ?? new Date();
182
+ const root = config.root;
183
+ const timeoutMs = opts.probeTimeoutMs ?? 800;
184
+ // ── server ──
185
+ const locks = readServeLocks(root, config.cacheDir);
186
+ // The primary lock is live-first, then most recent — its facts are reported
187
+ // even when dead, because "lockfile names pid X, which is gone" is exactly
188
+ // the diagnostic a stopped-but-should-be-running repo needs.
189
+ const primary = locks[0] ?? null;
190
+ const primaryAlive = primary?.alive ?? false;
191
+ // Probe the live lock's port; else a stale lock's port (the "lock is dead —
192
+ // is anything still on it?" diagnostic); else this repo's default port.
193
+ const probePort = opts.probePort ?? primary?.port ?? resolveServePort(root, config);
194
+ const health = await probeHealth(probePort, root, timeoutMs);
195
+ // Ground "running" in the port: when /api/health is unreachable, check
196
+ // whether anything is actually listening before trusting the lock's
197
+ // (possibly recycled) live PID.
198
+ const portActive = health.state !== "unreachable" || (await isPortListening(probePort, "127.0.0.1"));
199
+ const running = primaryAlive ? portActive : health.state === "ok";
200
+ let startedAt = primary?.startedAt ?? null;
201
+ let startedAtSource = startedAt ? "lockfile" : null;
202
+ if (!startedAt && health.state === "ok" && health.serverStartedAt) {
203
+ // Thin lockfile — fall back to /api/health, as the spec asks.
204
+ startedAt = health.serverStartedAt;
205
+ startedAtSource = "health";
206
+ }
207
+ const uptimeMs = startedAt !== null ? Math.max(0, now.getTime() - Date.parse(startedAt)) : null;
208
+ const server = {
209
+ running,
210
+ port: primary?.port ?? probePort,
211
+ pid: primary?.pid ?? null,
212
+ host: primary?.host ?? null,
213
+ startedAt,
214
+ startedAtSource,
215
+ uptimeSeconds: uptimeMs !== null && Number.isFinite(uptimeMs) ? uptimeMs / 1000 : null,
216
+ health: health.state,
217
+ healthRoot: health.root,
218
+ locks: locks.length,
219
+ };
220
+ // ── build ──
221
+ const check = checkBuildForRoot(root);
222
+ const build = {
223
+ code: check.code,
224
+ stale: check.stale,
225
+ applicable: check.applicable,
226
+ message: check.message,
227
+ version: readVersionFromMarker(root) ?? health.version,
228
+ buildAt: readBuildStamp(root),
229
+ };
230
+ // ── board ──
231
+ const idx = buildIndex(config);
232
+ const active = idx.tasks
233
+ .filter((t) => t.status === "active")
234
+ .map((t) => {
235
+ const wt = t.git.worktreePath;
236
+ const missing = !!t.branch && (!wt || !existsSync(wt));
237
+ return {
238
+ id: t.id,
239
+ title: t.title,
240
+ branch: t.branch,
241
+ worktreePath: wt,
242
+ worktreeMissing: missing,
243
+ updatedAt: t.updated_at,
244
+ needsInput: t.needsInput,
245
+ };
246
+ });
247
+ // ── worktrees ──
248
+ // Same sweep `repoos gc --dry-run` runs, fed the index we already built so
249
+ // the board is only walked once. The counts therefore match gc by
250
+ // construction, not by coincidence.
251
+ const gc = sweepStaleWorktrees(config, { mode: "full", dryRun: true, tasks: idx.tasks });
252
+ const worktrees = {
253
+ count: countWorktrees(root),
254
+ warnThreshold: config.worktreeWarnThreshold ?? 20,
255
+ leaked: gc.removedWorktrees.map((w) => ({ branch: w.branch, path: w.path })),
256
+ kept: gc.keptDirty.map((k) => ({ branch: k.branch, path: k.path, reason: k.reason })),
257
+ };
258
+ // ── tunnel ──
259
+ const tunnelCfg = readTunnelConfig(root);
260
+ const configured = !!tunnelCfg.tunnelId;
261
+ let tunnelRunning = false;
262
+ // Machine-wide view (any repo's apps, from the registry), same merge
263
+ // `/api/tunnel/readiness` does — falls back to this repo's own apps when
264
+ // the registry hasn't been seeded yet.
265
+ const registry = readRegistry();
266
+ reconcileIdentity(registry, tunnelCfg);
267
+ syncFromRepo(registry, tunnelCfg, root);
268
+ let hostnames = Object.values({ ...tunnelCfg.apps, ...unionApps(registry) })
269
+ .map((a) => a.hostname)
270
+ .sort();
271
+ if (configured) {
272
+ tunnelRunning = tunnelProcessRunning() || tunnelServiceRunning();
273
+ if (health.state === "ok") {
274
+ // Server is up — prefer its readiness view (same data, live). Best
275
+ // effort only: on auth-protected servers this endpoint 401s (the CLI
276
+ // has no session), and the local answer below is identical to what
277
+ // `repoos tunnel status` computes, so nothing is lost.
278
+ try {
279
+ const res = await fetch(`http://127.0.0.1:${probePort}/api/tunnel/readiness`, {
280
+ signal: AbortSignal.timeout(Math.max(timeoutMs, 2000)),
281
+ });
282
+ if (res.ok) {
283
+ const body = (await res.json());
284
+ if (typeof body.running === "boolean")
285
+ tunnelRunning = body.running;
286
+ if (Array.isArray(body.publishedHostnames)) {
287
+ hostnames = body.publishedHostnames
288
+ .filter((h) => typeof h === "string")
289
+ .sort();
290
+ }
291
+ }
292
+ }
293
+ catch {
294
+ /* readiness is enrichment only — local answer stands */
295
+ }
296
+ }
297
+ }
298
+ // ── git (the main checkout — the repo-as-OS itself) ──
299
+ const branch = currentBranch(root);
300
+ let clean = true;
301
+ let dirtyFiles = 0;
302
+ let ahead = null;
303
+ let behind = null;
304
+ if (branch) {
305
+ const st = await runGit(root, ["status", "--porcelain"], 4000);
306
+ if (st.status === 0) {
307
+ dirtyFiles = st.stdout.split("\n").filter((l) => l.trim() !== "").length;
308
+ clean = dirtyFiles === 0;
309
+ }
310
+ if (branch !== "main") {
311
+ const [a, b] = await Promise.all([
312
+ runGit(root, ["rev-list", "--count", `main..${branch}`], 4000),
313
+ runGit(root, ["rev-list", "--count", `${branch}..main`], 4000),
314
+ ]);
315
+ ahead = a.status === 0 ? Number(a.stdout.trim()) || 0 : null;
316
+ behind = b.status === 0 ? Number(b.stdout.trim()) || 0 : null;
317
+ }
318
+ }
319
+ return {
320
+ generatedAt: now.toISOString(),
321
+ root,
322
+ server,
323
+ build,
324
+ board: {
325
+ taskCount: idx.taskCount,
326
+ counts: idx.counts,
327
+ active,
328
+ },
329
+ worktrees,
330
+ tunnel: {
331
+ configured,
332
+ tunnelName: configured ? tunnelCfg.name : null,
333
+ running: tunnelRunning,
334
+ hostnames,
335
+ },
336
+ git: {
337
+ branch,
338
+ clean,
339
+ dirtyFiles,
340
+ isMainBranch: branch === "main",
341
+ ahead,
342
+ behind,
343
+ },
344
+ };
345
+ }
346
+ // ── Formatting helpers ───────────────────────────────────────────────────────
347
+ /** "42s" | "5m 07s" | "3h 42m" | "2d 4h" */
348
+ export function formatUptime(ms) {
349
+ const s = Math.max(0, Math.floor(ms / 1000));
350
+ if (s < 60)
351
+ return `${s}s`;
352
+ const m = Math.floor(s / 60);
353
+ if (m < 60)
354
+ return `${m}m ${String(s % 60).padStart(2, "0")}s`;
355
+ const h = Math.floor(m / 60);
356
+ if (h < 24)
357
+ return `${h}h ${String(m % 60).padStart(2, "0")}m`;
358
+ return `${Math.floor(h / 24)}d ${h % 24}h`;
359
+ }
360
+ const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
361
+ /** Local "14:02" on the same day, else "Sep 2 14:02". */
362
+ export function formatSince(iso, now) {
363
+ const d = new Date(iso);
364
+ if (Number.isNaN(d.getTime()))
365
+ return "?";
366
+ const hm = `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
367
+ const sameDay = d.getFullYear() === now.getFullYear() &&
368
+ d.getMonth() === now.getMonth() &&
369
+ d.getDate() === now.getDate();
370
+ return sameDay ? hm : `${MONTHS[d.getMonth()]} ${d.getDate()} ${hm}`;
371
+ }
372
+ /** "41s ago" | "5m ago" | "3h 02m ago" | "2d ago" — for last-activity stamps. */
373
+ export function formatRel(iso, now) {
374
+ if (!iso)
375
+ return "?";
376
+ const ms = now.getTime() - Date.parse(iso);
377
+ if (!Number.isFinite(ms))
378
+ return "?";
379
+ const s = Math.max(0, Math.floor(ms / 1000));
380
+ if (s < 60)
381
+ return `${s}s ago`;
382
+ const m = Math.floor(s / 60);
383
+ if (m < 60)
384
+ return `${m}m ago`;
385
+ const h = Math.floor(m / 60);
386
+ if (h < 24)
387
+ return `${h}h ${String(m % 60).padStart(2, "0")}m ago`;
388
+ return `${Math.floor(h / 24)}d ago`;
389
+ }
390
+ function truncate(s, n) {
391
+ return s.length <= n ? s : s.slice(0, n - 1) + "…";
392
+ }
393
+ // ── Rendering ────────────────────────────────────────────────────────────────
394
+ const LABEL = 10;
395
+ function row(label, text) {
396
+ console.log(" " + c.dim(label.padEnd(LABEL)) + text);
397
+ }
398
+ function sub(text) {
399
+ console.log(" " + " ".repeat(LABEL) + text);
400
+ }
401
+ export function renderStatus(s, now = new Date()) {
402
+ console.log("");
403
+ console.log(" " + c.bold(c.cyan("RepoOS status")) + c.dim(" — " + basename(s.root)));
404
+ console.log(c.dim(" " + s.root));
405
+ // Stale build FIRST and loud — per AGENTS.md it is the #1 time-waster in
406
+ // this repo; it must never read as a quiet footnote.
407
+ // Only when the RepoOS build contract applies: no dist/ or no marker means
408
+ // this checkout isn't using our build pipeline, so the "skip" message isn't a
409
+ // warning (#0349).
410
+ const buildCheckApplicable = s.build.code !== "no-build" && s.build.code !== "no-marker";
411
+ if (s.build.stale && buildCheckApplicable && s.build.message) {
412
+ console.log("");
413
+ for (const line of s.build.message.split("\n")) {
414
+ console.log(c.bold(c.yellow(" ⚠ " + line.trim())));
415
+ }
416
+ }
417
+ console.log("");
418
+ // server
419
+ const sv = s.server;
420
+ if (sv.running) {
421
+ const bits = [];
422
+ if (sv.port !== null)
423
+ bits.push(`port ${sv.port}`);
424
+ if (sv.pid !== null)
425
+ bits.push(`pid ${sv.pid}`);
426
+ if (sv.startedAt) {
427
+ bits.push(`up ${formatUptime((sv.uptimeSeconds ?? 0) * 1000)} (since ${formatSince(sv.startedAt, now)})`);
428
+ }
429
+ else {
430
+ bits.push("start time unknown");
431
+ }
432
+ row("server", c.green("● running") + c.dim(" · ") + bits.join(c.dim(" · ")));
433
+ if (sv.health === "foreign") {
434
+ sub(c.yellow(`⚠ port ${sv.port} answers, but it serves ${sv.healthRoot ?? "a different repo"} — wrong port?`));
435
+ }
436
+ else if (sv.health === "unreachable") {
437
+ sub(c.yellow(`⚠ port ${sv.port} is listening but /api/health is not answering — the server may be hung`));
438
+ }
439
+ else if (sv.pid === null) {
440
+ sub(c.dim("no serve lockfile — live via /api/health; restart `repoos serve` to restore it"));
441
+ }
442
+ if (sv.locks > 1)
443
+ sub(c.dim(`+ ${sv.locks - 1} more serve lock(s) — check other ports`));
444
+ }
445
+ else {
446
+ let line = c.red("○ stopped") + c.dim(" — no live serve process for this repo");
447
+ if (sv.pid !== null) {
448
+ line +=
449
+ "\n" +
450
+ " ".repeat(LABEL) +
451
+ c.dim(`last lock: pid ${sv.pid}` +
452
+ (sv.port !== null ? ` · port ${sv.port}` : "") +
453
+ (sv.startedAt ? ` · started ${formatSince(sv.startedAt, now)}` : ""));
454
+ }
455
+ if (sv.health === "foreign") {
456
+ line +=
457
+ "\n" +
458
+ " ".repeat(LABEL) +
459
+ c.yellow(`⚠ but port ${sv.port} is answering for ${sv.healthRoot ?? "another repo"} — wrong port?`);
460
+ }
461
+ row("server", line);
462
+ }
463
+ // build
464
+ const buildBits = [
465
+ s.build.stale ? c.yellow("● stale") : c.green("● fresh"),
466
+ s.build.version ? c.dim("repoos v" + s.build.version) : c.dim("version unknown"),
467
+ s.build.buildAt
468
+ ? c.dim("built " + formatSince(s.build.buildAt, now))
469
+ : c.dim("build time unknown"),
470
+ ];
471
+ row("build", buildBits.join(c.dim(" · ")));
472
+ if (s.build.code === "no-build" || s.build.code === "published") {
473
+ sub(c.dim("(no dist build — source checkout)"));
474
+ }
475
+ // board
476
+ const counts = STATUSES.map((st) => `${st} ${s.board.counts[st] ?? 0}`).join(c.dim(" · "));
477
+ row("board", c.bold(String(s.board.taskCount)) + c.dim(" tasks · ") + counts);
478
+ for (const t of s.board.active) {
479
+ const flags = [];
480
+ if (t.needsInput)
481
+ flags.push(c.yellow("waiting for you"));
482
+ if (t.worktreeMissing)
483
+ flags.push(c.red("⚠ worktree missing"));
484
+ console.log("\n" +
485
+ " " +
486
+ c.dim("#" + t.id) +
487
+ " " +
488
+ truncate(t.title, 60) +
489
+ c.dim(" · updated " + formatRel(t.updatedAt, now)) +
490
+ (flags.length ? " " + flags.join(c.dim(" · ")) : ""));
491
+ sub(c.dim("branch ") + (t.branch ? c.cyan(truncate(t.branch, 80)) : c.dim("— none yet")));
492
+ sub(c.dim("worktree ") +
493
+ (t.worktreePath && !t.worktreeMissing
494
+ ? c.dim(truncate(t.worktreePath, 100))
495
+ : t.worktreeMissing
496
+ ? c.red("missing")
497
+ : c.dim("none")));
498
+ }
499
+ if (s.board.active.length === 0)
500
+ sub(c.dim("nothing active"));
501
+ // worktrees
502
+ const threshold = s.worktrees.warnThreshold;
503
+ const wtBits = [`${s.worktrees.count} registered`];
504
+ if (threshold > 0)
505
+ wtBits.push(`advisory ceiling ${threshold}`);
506
+ const leaked = s.worktrees.leaked;
507
+ const leakText = leaked.length === 0
508
+ ? c.dim("no leaks")
509
+ : c.yellow(`${leaked.length} leaked — run `) + c.cyan("repoos gc --dry-run");
510
+ row("worktrees", wtBits.join(c.dim(" · ")) + c.dim(" · ") + leakText);
511
+ for (const w of leaked)
512
+ sub(c.yellow("leaked ") + c.cyan(w.branch || "(detached)") + c.dim(" " + w.path));
513
+ for (const k of s.worktrees.kept) {
514
+ sub(c.dim("kept ") + c.cyan(k.branch || "(detached)") + c.dim(` — ${k.reason}`));
515
+ }
516
+ // tunnel
517
+ if (!s.tunnel.configured) {
518
+ row("tunnel", c.dim("not configured") + c.dim(" (") + c.cyan("repoos tunnel setup") + c.dim(")"));
519
+ }
520
+ else {
521
+ const state = s.tunnel.running ? c.green("running") : c.yellow("not running");
522
+ const hosts = s.tunnel.hostnames.length
523
+ ? `${s.tunnel.hostnames.length} published: ${s.tunnel.hostnames.join(", ")}`
524
+ : "no hostnames published";
525
+ row("tunnel", c.cyan(s.tunnel.tunnelName ?? "tunnel") + c.dim(" · ") + state + c.dim(" · " + hosts));
526
+ }
527
+ // git
528
+ if (!s.git.branch) {
529
+ row("git", c.dim("not a git repository"));
530
+ }
531
+ else {
532
+ const bits = [c.cyan(s.git.branch)];
533
+ bits.push(s.git.clean
534
+ ? c.green("clean")
535
+ : c.yellow(`dirty (${s.git.dirtyFiles} file${s.git.dirtyFiles === 1 ? "" : "s"})`));
536
+ if (!s.git.isMainBranch && (s.git.ahead !== null || s.git.behind !== null)) {
537
+ bits.push(c.dim(`↑${s.git.ahead ?? "?"} ↓${s.git.behind ?? "?"} vs main`));
538
+ }
539
+ row("git", bits.join(c.dim(" · ")));
540
+ }
541
+ console.log("");
542
+ }
543
+ // ── Command entry ────────────────────────────────────────────────────────────
544
+ /** `repoos status [--json]` */
545
+ export async function cmdStatus(argv) {
546
+ const asJson = argv.includes("--json");
547
+ try {
548
+ const { root, fromWorktree } = boardRoot();
549
+ if (fromWorktree) {
550
+ // stderr so `--json` stdout stays machine-clean — same note list/gc print.
551
+ console.error(c.yellow(" ⚠ ") +
552
+ c.dim("running from inside a linked worktree — reporting the MAIN checkout (") +
553
+ c.cyan(root) +
554
+ c.dim(")"));
555
+ }
556
+ const config = loadConfig(root);
557
+ const snapshot = await collectStatus(config);
558
+ if (asJson) {
559
+ console.log(JSON.stringify(snapshot, null, 2));
560
+ }
561
+ else {
562
+ renderStatus(snapshot);
563
+ }
564
+ }
565
+ catch (e) {
566
+ console.error(c.red(" repoos status failed: ") + e.message);
567
+ process.exitCode = 1;
568
+ }
569
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdStop(argv: string[]): void;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `repoos stop [--port N]` — stop THIS repo's running `repoos serve`
3
+ * process(es), by the PID recorded in its own `.repoos/serve-<port>.lock`.
4
+ *
5
+ * Replaces the machine-wide `pkill -f "dist/cli/index.js serve"` that also
6
+ * killed every other repo's server (and any preview) — a `repoos init` repo
7
+ * runs the same linked CLI, so the pattern is not repo-scoped.
8
+ */
9
+ import { readdirSync, readFileSync, rmSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { boardRoot } from "../core/config.js";
12
+ import { createRepoOS } from "../core/repoos.js";
13
+ import { c } from "../cli/colors.js";
14
+ export function cmdStop(argv) {
15
+ let portFilter;
16
+ for (let i = 0; i < argv.length; i++) {
17
+ if (argv[i] === "--port" || argv[i] === "-p")
18
+ portFilter = Number(argv[++i]);
19
+ }
20
+ const { root } = boardRoot();
21
+ const { config } = createRepoOS(root);
22
+ const lockDir = join(root, config.cacheDir);
23
+ let files;
24
+ try {
25
+ files = readdirSync(lockDir).filter((f) => /^serve(?:-\d+)?\.lock$/.test(f));
26
+ }
27
+ catch {
28
+ files = [];
29
+ }
30
+ if (portFilter)
31
+ files = files.filter((f) => f === `serve-${portFilter}.lock`);
32
+ let stopped = 0;
33
+ for (const file of files) {
34
+ const path = join(lockDir, file);
35
+ let info = null;
36
+ try {
37
+ info = JSON.parse(readFileSync(path, "utf8"));
38
+ }
39
+ catch {
40
+ rmSync(path, { force: true });
41
+ continue;
42
+ }
43
+ const pid = info?.pid;
44
+ if (typeof pid === "number" && pid > 0 && pid !== process.pid) {
45
+ try {
46
+ process.kill(pid, 0); // existence probe — throws when gone
47
+ process.kill(pid, "SIGTERM");
48
+ stopped++;
49
+ console.log(c.dim(` stopped repoos serve (pid ${pid}, port ${info.port ?? "?"})`));
50
+ }
51
+ catch {
52
+ /* already exited */
53
+ }
54
+ }
55
+ rmSync(path, { force: true });
56
+ }
57
+ if (stopped === 0)
58
+ console.log(c.dim(" no running repoos serve for this repo"));
59
+ }
@@ -0,0 +1,47 @@
1
+ /** `repoos list [status]` — board overview or a single column. */
2
+ export declare function cmdList(statusArg?: string): void;
3
+ /** `repoos show <id>` — full task detail. */
4
+ export declare function cmdShow(id?: string): void;
5
+ /**
6
+ * `repoos mv <id> <status>` — change status (frontmatter edit).
7
+ *
8
+ * Deliberately does NOT run this transition through `guardReviewTransition`
9
+ * (#0263), even for a move into `review`. That gate lives in the HTTP PATCH
10
+ * path because it operates on the task's OWN branch worktree — staging and
11
+ * committing pending implementation changes there and rejecting a vacuous
12
+ * (zero-source-change) transition — which is an agent-handoff guarantee, not
13
+ * a board-write guarantee. `repoos mv` is the low-level, generic "edit this
14
+ * frontmatter field" tool (a human or script can move ANY task to ANY status,
15
+ * with or without a branch or worktree at all); forcing every review move
16
+ * through worktree resolution would turn a one-line status edit into a hard
17
+ * dependency on handoff plumbing that plenty of legitimate `mv` calls don't
18
+ * have. The bug this task fixes is narrower and applies to every status
19
+ * change here regardless of target: `updateStatus` (via `rewrite()` in
20
+ * core/repoos.ts) now always commits the task file in the main checkout, so
21
+ * the write itself is never left as an untrusted dirty file. Agents that want
22
+ * the full handoff guarantee (implementation committed + non-vacuous) should
23
+ * go through the trusted handoff/PATCH path, not this CLI shortcut.
24
+ */
25
+ export declare function cmdMv(id?: string, status?: string, note?: string): void;
26
+ /**
27
+ * `repoos note <id> "<text>"` — append a short, free-form note to a task's
28
+ * activity log, so a PM/reviewer can send guidance back to the developer (or
29
+ * record any free-form note) without rewriting the task body. The note is
30
+ * recorded as its own activity entry and surfaces wherever the task's
31
+ * history is shown. Board-rooted, not cwd-rooted (#0202) — see cmdMv.
32
+ */
33
+ export declare function cmdNote(args: string[]): void;
34
+ /**
35
+ * `repoos update <id> [--title ...] [--area ...] [--priority ...] [--type ...]
36
+ * [--body ... | --body -] [--branch ...] [--assigned-to ai|human]`
37
+ *
38
+ * Writes directly via patchTaskFile (same path the server's PATCH route uses),
39
+ * so it works with no HTTP round-trip and no session auth — this is the path
40
+ * agents/scripts should use to edit task metadata instead of hitting the API.
41
+ * `--body -` reads the new body from stdin, for large/multiline bodies.
42
+ */
43
+ export declare function cmdUpdate(args: string[]): void;
44
+ /** `repoos new <title> [--ai] [--type t] [--area a] [--priority p] [--body "..."|-]` */
45
+ export declare function cmdNew(args: string[]): void;
46
+ /** `repoos index [--json]` — rebuild cache; optionally print machine-readable JSON. */
47
+ export declare function cmdIndex(args: string[]): void;