@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,491 @@
1
+ /**
2
+ * Reap stale and orphaned repoos serve processes (task 0168).
3
+ *
4
+ * Manages a single lockfile under `.repoos/serve.lock` that tracks the PID of
5
+ * the serve process serving a given port. On startup, stale processes are
6
+ * detected and reaped. Port binding conflicts are detected before any bind
7
+ * attempt so serve refuses to coexist silently with a live server.
8
+ *
9
+ * Windows limitation: process alive-check is best-effort (kill -0 support
10
+ * varies). The reaper is primarily for Unix/Mac. On Windows, rely on the
11
+ * OS to reject EADDRINUSE if a port is already bound.
12
+ *
13
+ * Zero runtime deps: node:fs / node:child_process / node:path only.
14
+ */
15
+ import { existsSync, realpathSync, readFileSync, writeFileSync, rmSync, mkdirSync } from "node:fs";
16
+ import { join, dirname, sep } from "node:path";
17
+ import { execFile, execSync } from "node:child_process";
18
+ import { tmpdir } from "node:os";
19
+ import net from "node:net";
20
+ /** Concurrency cap for the boot-time orphan sweep's per-process cwd lookups. */
21
+ const ORPHAN_SWEEP_CONCURRENCY = 16;
22
+ /** Consecutive missing-root checks before a serve process closes itself. */
23
+ const WATCH_MISSES_REQUIRED = 3;
24
+ /**
25
+ * Manages a single lockfile that tracks the live serve process for a repo.
26
+ * At startup, detects and reaps stale processes. Prevents port conflicts.
27
+ * Skip cleanup when spawned as a reload replacement (REPOOS_RELOAD=1) so
28
+ * the parent can exit gracefully through its close handler.
29
+ */
30
+ export class ServeReaper {
31
+ lockPath;
32
+ pid = process.pid;
33
+ repoRoot;
34
+ /** Ephemeral test/harness servers must never touch the control-plane lock. */
35
+ enabled;
36
+ registered = false;
37
+ rootWatch = null;
38
+ /**
39
+ * A preview child (`repoos serve --port <ephemeral>` rooted at a task
40
+ * worktree) is NOT the control-plane server, so the single-per-repo serve
41
+ * lockfile and its stale-reaping/conflict logic don't apply to it. If it ran
42
+ * `cleanupStale`, it would reap whatever sibling preview happens to be in the
43
+ * worktree's lockfile (killing a booting preview mid-health-check → "did not
44
+ * become ready"), and because ephemeral ports can be reused, `detectConflict`
45
+ * could even refuse to bind a port that is already stale in the lockfile.
46
+ * Disable the reaper entirely for preview children (#0183).
47
+ */
48
+ previewChild = process.env.REPOOS_PREVIEW_CHILD === "1";
49
+ constructor(repoRoot, cacheDir = ".repoos", enabled = true, port) {
50
+ this.repoRoot = repoRoot;
51
+ // Per-PORT lockfile. A repo can legitimately run more than one control
52
+ // plane (the dogfood `just serve` on :7171 and Claude Code's Browser-pane
53
+ // preview on another port). With a single `serve.lock`, whichever booted
54
+ // last reaped the other via `cleanupStale` (it kills the lock's PID without
55
+ // checking the port). Scoping the lock by port means each server only ever
56
+ // sees — and only ever reaps a stale predecessor of — its own endpoint.
57
+ this.lockPath = join(repoRoot, cacheDir, Number.isInteger(port) && port > 0 ? `serve-${port}.lock` : "serve.lock");
58
+ this.enabled = enabled;
59
+ }
60
+ /**
61
+ * Close this server when the checkout it serves disappears. Fixture and
62
+ * preview roots are frequently removed before their child process receives
63
+ * its normal shutdown signal; a lockfile inside that deleted root can no
64
+ * longer help a later startup reap it. The watch is deliberately owned by
65
+ * the server process, so it also covers standalone fixture `serve` calls.
66
+ *
67
+ * A real repo root can be momentarily invisible (a rename while the dir is
68
+ * moved, a network-FS blip) without being gone — tearing the server down on
69
+ * such a transient miss would kill the live control plane. The root must
70
+ * be missing for `missesRequired` consecutive checks before `onMissing`
71
+ * fires; a deleted fixture/preview root stays gone, so this only delays the
72
+ * self-close by `missesRequired × intervalMs`.
73
+ */
74
+ watchRoot(onMissing, intervalMs = 1_000, missesRequired = WATCH_MISSES_REQUIRED) {
75
+ this.stopWatchingRoot();
76
+ let misses = 0;
77
+ const check = () => {
78
+ if (existsSync(this.repoRoot)) {
79
+ misses = 0;
80
+ return;
81
+ }
82
+ misses += 1;
83
+ if (misses < missesRequired)
84
+ return;
85
+ this.stopWatchingRoot();
86
+ onMissing();
87
+ };
88
+ this.rootWatch = setInterval(check, intervalMs);
89
+ this.rootWatch.unref?.();
90
+ return () => this.stopWatchingRoot();
91
+ }
92
+ /**
93
+ * Check if a process with the given PID is still running and matches our
94
+ * expected serve characteristics (the repoos CLI binary in the command line).
95
+ * On Windows, the check is limited to existence (kill -0).
96
+ */
97
+ isProcessAlive(pid, port) {
98
+ if (!Number.isInteger(pid) || pid <= 0)
99
+ return false;
100
+ // For the current process, trust it's valid without checking
101
+ if (pid === this.pid)
102
+ return true;
103
+ try {
104
+ // Check if process exists (works on Unix and Windows)
105
+ execSync(`kill -0 ${pid}`, { stdio: "ignore", timeout: 2000 });
106
+ }
107
+ catch {
108
+ return false;
109
+ }
110
+ // On Windows, we can only verify existence, not the cmdline. Return true.
111
+ if (process.platform === "win32")
112
+ return true;
113
+ // On Unix/Mac, verify it's a repoos serve process on the expected port
114
+ try {
115
+ const cmdline = execSync(`ps -p ${pid} -o command=`, {
116
+ encoding: "utf8",
117
+ stdio: ["ignore", "pipe", "ignore"],
118
+ timeout: 2000,
119
+ });
120
+ return cmdline.includes("serve") && cmdline.includes(`--port ${port}`);
121
+ }
122
+ catch {
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ * Boot-time cleanup: detect and reap stale processes from the lockfile.
128
+ * SKIPPED when spawned as a reload replacement (REPOOS_RELOAD=1) so the
129
+ * parent process can exit gracefully without being killed mid-shutdown.
130
+ * This is safe to call multiple times and always succeeds (best-effort).
131
+ */
132
+ cleanupStale() {
133
+ if (!this.enabled)
134
+ return;
135
+ // A preview child must never reap other processes (see `previewChild`).
136
+ if (this.previewChild)
137
+ return;
138
+ // Skip cleanup when spawned as a reload replacement — the parent process
139
+ // is still running and will shut down gracefully. Killing it here would
140
+ // bypass previews.stopAll() and runner.flushAll(), orphaning children.
141
+ if (process.env.REPOOS_RELOAD === "1")
142
+ return;
143
+ if (!existsSync(this.lockPath))
144
+ return;
145
+ let old = null;
146
+ try {
147
+ old = JSON.parse(readFileSync(this.lockPath, "utf8"));
148
+ }
149
+ catch {
150
+ // Corrupt lockfile — drop it
151
+ this.removeLock();
152
+ return;
153
+ }
154
+ if (!old || typeof old.pid !== "number" || typeof old.port !== "number") {
155
+ this.removeLock();
156
+ return;
157
+ }
158
+ // If the lockfile claims our own PID, it's stale from a prior launchd run
159
+ // that recycled this PID — don't kill ourselves.
160
+ if (old.pid === this.pid) {
161
+ this.removeLock();
162
+ return;
163
+ }
164
+ // If there's a stale process, try to reap it
165
+ if (!this.isProcessAlive(old.pid, old.port)) {
166
+ this.removeLock();
167
+ return;
168
+ }
169
+ // Process is still running. Try to kill it since it's stale
170
+ this.killProcess(old.pid);
171
+ this.removeLock();
172
+ }
173
+ /**
174
+ * Reap historical fixture/preview servers whose deleted root also took their
175
+ * lockfile with it. This is intentionally narrower than a generic process
176
+ * sweep: it requires the RepoOS CLI's `serve` command shape AND a cwd under
177
+ * the system temp dir that no longer exists — the exact shape of every
178
+ * observed orphan (`/var/folders/.../repoos-release-*`, `.../repoos-autoprev-*`).
179
+ * A user's live control plane, every healthy preview, and a sibling project
180
+ * that happens to be briefly unmounted or renamed therefore remain untouched
181
+ * (a real repo never lives under tmpdir).
182
+ *
183
+ * Async and best-effort so a boot full of accumulated orphans can never
184
+ * block serve startup: the `ps` scan and the per-process `lsof` cwd lookups
185
+ * run off the event loop, with the lookups capped in flight. Returns the
186
+ * number of processes killed.
187
+ */
188
+ async cleanupOrphanedRoots() {
189
+ if (!this.enabled)
190
+ return 0;
191
+ if (process.platform === "win32")
192
+ return 0;
193
+ let rows;
194
+ try {
195
+ rows = await execFileAsync("ps", ["-axo", "pid=,command="], 4_000);
196
+ }
197
+ catch {
198
+ return 0;
199
+ }
200
+ const candidates = [];
201
+ for (const row of rows.split("\n")) {
202
+ const match = row.trim().match(/^(\d+)\s+(.+)$/);
203
+ if (!match)
204
+ continue;
205
+ const pid = Number(match[1]);
206
+ const command = match[2];
207
+ if (pid === this.pid || !isOrphanServeCommand(command))
208
+ continue;
209
+ candidates.push(pid);
210
+ }
211
+ if (candidates.length === 0)
212
+ return 0;
213
+ let reaped = 0;
214
+ await runBounded(candidates, ORPHAN_SWEEP_CONCURRENCY, async (pid) => {
215
+ const cwd = await this.processCwdAsync(pid);
216
+ if (!cwd || !isOrphanRoot(cwd))
217
+ return;
218
+ // PID-recycling guard: the command-shape scan ran at sweep start, so a
219
+ // PID could have been reused by an unrelated process in the interim.
220
+ // Never signal a PID that no longer names a serve process at kill time.
221
+ const command = await this.commandOf(pid);
222
+ if (!command || !isOrphanServeCommand(command))
223
+ return;
224
+ this.killProcess(pid);
225
+ reaped += 1;
226
+ });
227
+ return reaped;
228
+ }
229
+ /**
230
+ * Detect if a port is already bound by a live serve process.
231
+ * Returns a human-readable error message if there's a conflict, null otherwise.
232
+ *
233
+ * Two independent signals are consulted:
234
+ * 1. The live port probe (new): is *something* actually listening? Consulted
235
+ * first so a missing/stale/corrupt lockfile can no longer mask a live
236
+ * listener — the single source of truth for "is the port taken" is the
237
+ * port itself, not the lockfile (#0284).
238
+ * 2. The lockfile (existing): when it names a live process for this exact
239
+ * port/host, that yields the most specific conflict (PID + start time).
240
+ *
241
+ * The probe matters because binding a port a lockfile-less-but-live process
242
+ * owns would otherwise either EADDRINUSE with a confusing error or, worse,
243
+ * silently steal a port mid-drain during another process's reload.
244
+ */
245
+ async detectConflict(port, host) {
246
+ if (!this.enabled)
247
+ return null;
248
+ // Preview children bind distinct ephemeral ports; the control-plane
249
+ // conflict check (which reads the shared per-worktree lockfile) does not
250
+ // apply and can false-positive on a reused port (see `previewChild`).
251
+ if (this.previewChild)
252
+ return null;
253
+ // "0.0.0.0" is a valid bind address but not a connectable one — probe the
254
+ // loopback interface instead. Ephemeral (port 0) means "pick a free port",
255
+ // so there is never a listener to probe.
256
+ const probeHost = host === "0.0.0.0" ? "127.0.0.1" : host;
257
+ const listening = port !== 0 ? await isPortListening(port, probeHost) : false;
258
+ let info = null;
259
+ if (existsSync(this.lockPath)) {
260
+ try {
261
+ info = JSON.parse(readFileSync(this.lockPath, "utf8"));
262
+ }
263
+ catch {
264
+ info = null; // corrupt — fall through to the probe result
265
+ }
266
+ }
267
+ // A lockfile that names a live process for this exact port/host is the most
268
+ // specific conflict: we can point the user at the offending PID.
269
+ if (info && info.port === port && info.host === host && this.isProcessAlive(info.pid, port)) {
270
+ return (`Port ${port} is already bound by another repoos serve process (PID ${info.pid} started at ${info.startedAt}). ` +
271
+ `Use 'kill ${info.pid}' to stop it, or choose a different port with --port.`);
272
+ }
273
+ // A lockfile that exists for this exact port/host but names a dead process
274
+ // is stale — clear it so a later startup (and our own register below)
275
+ // starts from a clean slate. Only when the process is actually gone.
276
+ if (info && info.port === port && info.host === host) {
277
+ this.removeLock();
278
+ }
279
+ // A live listener the lockfile doesn't explain is still a conflict: binding
280
+ // would either EADDRINUSE or steal a port some live process — possibly
281
+ // another serve — already holds (#0284). The message distinguishes the two
282
+ // reasons the lockfile can differ from reality so a present-and-valid
283
+ // lockfile (for a different port/host) isn't dismissed as "missing/stale".
284
+ if (listening) {
285
+ // We reach here only when the lockfile couldn't explain the live listener.
286
+ // Same endpoint + live PID was handled above; same endpoint + dead PID was
287
+ // just reaped (stale). Anything else means the lockfile points elsewhere,
288
+ // or is absent — so say which, rather than blanket-claiming "missing/stale".
289
+ const lockAccounted = info === null
290
+ ? "the serve lockfile is missing or corrupt"
291
+ : info.port === port && info.host === host
292
+ ? "the serve lockfile names a dead process on this port"
293
+ : `the serve lockfile names a different endpoint (${info.host}:${info.port})`;
294
+ return (`Port ${port} is already in use by a live process on ${probeHost}, but ${lockAccounted}. ` +
295
+ `Refusing to bind rather than steal a port a live process owns — choose a different port with --port.`);
296
+ }
297
+ return null;
298
+ }
299
+ /**
300
+ * Register the current process as serving on the given port.
301
+ * Call this after successful bind. Idempotent.
302
+ */
303
+ register(port, host) {
304
+ // Preview children don't own the control-plane lockfile; writing it would
305
+ // collide with the worktree's other preview cycles (see `previewChild`).
306
+ if (!this.enabled || this.previewChild)
307
+ return;
308
+ try {
309
+ mkdirSync(dirname(this.lockPath), { recursive: true });
310
+ const info = {
311
+ pid: this.pid,
312
+ port,
313
+ host,
314
+ startedAt: new Date().toISOString(),
315
+ };
316
+ writeFileSync(this.lockPath, JSON.stringify(info, null, 2));
317
+ this.registered = true;
318
+ }
319
+ catch {
320
+ // Registration is best-effort — never crash the server
321
+ }
322
+ }
323
+ /**
324
+ * Unregister the current process. Call on shutdown.
325
+ * Idempotent: unregistering when not registered is a no-op.
326
+ */
327
+ unregister() {
328
+ this.stopWatchingRoot();
329
+ // An ephemeral server used the same repo root but never registered itself;
330
+ // it must not delete the long-lived control plane's lock on close.
331
+ if (!this.registered)
332
+ return;
333
+ this.removeLock();
334
+ this.registered = false;
335
+ }
336
+ // ---- internals ----
337
+ removeLock() {
338
+ try {
339
+ rmSync(this.lockPath, { force: true });
340
+ }
341
+ catch {
342
+ /* ignore */
343
+ }
344
+ }
345
+ stopWatchingRoot() {
346
+ if (this.rootWatch === null)
347
+ return;
348
+ clearInterval(this.rootWatch);
349
+ this.rootWatch = null;
350
+ }
351
+ /** Read a process cwd from lsof's machine-readable output, best-effort. */
352
+ async processCwdAsync(pid) {
353
+ try {
354
+ const out = await execFileAsync("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], 2_000);
355
+ const line = out.split("\n").find((entry) => entry.startsWith("n"));
356
+ const cwd = line?.slice(1) || null;
357
+ // macOS lsof suffixes a deleted cwd with " (deleted)" — exactly the case
358
+ // the orphan sweep looks for, so strip it before the root checks.
359
+ return cwd ? cwd.replace(/ \(deleted\)$/, "") : null;
360
+ }
361
+ catch {
362
+ return null;
363
+ }
364
+ }
365
+ /** The command line of `pid`, or null when the process is already gone. */
366
+ async commandOf(pid) {
367
+ try {
368
+ const out = await execFileAsync("ps", ["-p", String(pid), "-o", "command="], 2_000);
369
+ return out.trim() || null;
370
+ }
371
+ catch {
372
+ return null;
373
+ }
374
+ }
375
+ killProcess(pid) {
376
+ try {
377
+ // Use process.kill() which is portable across Unix/Mac/Windows.
378
+ // Send SIGTERM first (graceful), then SIGKILL only if the process is
379
+ // still alive at the deadline. Never SIGKILL a PID that exited in the
380
+ // grace window — an unrelated process may have recycled it (#0216).
381
+ process.kill(pid, "SIGTERM");
382
+ }
383
+ catch {
384
+ /* ignore — process may already be gone */
385
+ return;
386
+ }
387
+ setTimeout(() => {
388
+ try {
389
+ process.kill(pid, 0); // existence probe — throws ESRCH when gone
390
+ process.kill(pid, "SIGKILL");
391
+ }
392
+ catch {
393
+ /* ignore — already exited; do not SIGKILL a possibly-recycled PID */
394
+ }
395
+ }, 100);
396
+ }
397
+ }
398
+ /**
399
+ * True when a TCP connection can be established to host:port — i.e. some
400
+ * process is actually listening there. This is the ground truth for "is the
401
+ * port taken", consulted alongside the lockfile so a missing/stale/corrupt
402
+ * lockfile can't mask a live listener (#0284). Best-effort and async: any
403
+ * connect error (connection refused, timeout, unroutable host) resolves false,
404
+ * and an invalid port resolves false immediately.
405
+ */
406
+ export function isPortListening(port, host, timeoutMs = 1000) {
407
+ return new Promise((resolve) => {
408
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) {
409
+ resolve(false);
410
+ return;
411
+ }
412
+ const socket = net.connect({ port, host });
413
+ let settled = false;
414
+ const done = (ok) => {
415
+ if (settled)
416
+ return;
417
+ settled = true;
418
+ socket.destroy();
419
+ resolve(ok);
420
+ };
421
+ socket.setTimeout(timeoutMs, () => done(false));
422
+ socket.once("connect", () => done(true));
423
+ socket.once("error", () => done(false));
424
+ });
425
+ }
426
+ /**
427
+ * True when a process command line has the RepoOS CLI `serve` shape — the
428
+ * compiled `.../cli/index.js serve` or dev `.../src/cli/index.ts serve`. The
429
+ * orphan sweep requires this shape in addition to a deleted temp-dir root, so
430
+ * unrelated processes are never touched.
431
+ */
432
+ export function isOrphanServeCommand(command) {
433
+ return /cli[/\\]index\.(?:js|ts)/.test(command) && /\sserve(?:\s|$)/.test(command);
434
+ }
435
+ let cachedTempDirs = null;
436
+ /**
437
+ * The system temp dir and its real path. macOS exposes `/var` as a symlink
438
+ * to `/private/var`, and lsof reports the resolved path, so both forms are
439
+ * kept and compared.
440
+ */
441
+ function systemTempDirs() {
442
+ if (cachedTempDirs)
443
+ return cachedTempDirs;
444
+ const raw = tmpdir();
445
+ const dirs = new Set([raw]);
446
+ try {
447
+ dirs.add(realpathSync(raw));
448
+ }
449
+ catch {
450
+ /* the temp dir always exists */
451
+ }
452
+ cachedTempDirs = [...dirs];
453
+ return cachedTempDirs;
454
+ }
455
+ /** True when `cwd` is at or under the system temp dir. */
456
+ function isUnderSystemTempDir(cwd) {
457
+ return systemTempDirs().some((d) => cwd === d || cwd.startsWith(d + sep));
458
+ }
459
+ /**
460
+ * True when `cwd` is a deleted root under the system temp dir — the exact
461
+ * shape of every observed orphan (fixture/preview temp dirs). A real repo —
462
+ * the live control plane, a preview worktree, any sibling project — never
463
+ * lives under tmpdir, so a briefly-unmounted or renamed repo cannot be
464
+ * mistaken for an orphan and killed. Exported for testing.
465
+ */
466
+ export function isOrphanRoot(cwd) {
467
+ if (existsSync(cwd))
468
+ return false;
469
+ return isUnderSystemTempDir(cwd);
470
+ }
471
+ /** `execFile` promisified for the boot-time orphan sweep. */
472
+ function execFileAsync(cmd, args, timeoutMs) {
473
+ return new Promise((resolve, reject) => {
474
+ execFile(cmd, args, { encoding: "utf8", timeout: timeoutMs }, (error, stdout) => {
475
+ if (error)
476
+ reject(error);
477
+ else
478
+ resolve(stdout);
479
+ });
480
+ });
481
+ }
482
+ /** Run `fn` over `items` with at most `concurrency` promises in flight. */
483
+ async function runBounded(items, concurrency, fn) {
484
+ const queue = [...items];
485
+ const workers = Array.from({ length: Math.min(concurrency, queue.length) }, async () => {
486
+ for (let next = queue.shift(); next !== undefined; next = queue.shift()) {
487
+ await fn(next);
488
+ }
489
+ });
490
+ await Promise.all(workers);
491
+ }
@@ -0,0 +1,49 @@
1
+ import { LiveIndex } from "./live-index.js";
2
+ export interface ServeOptions {
3
+ root?: string;
4
+ port?: number;
5
+ host?: string;
6
+ /**
7
+ * True when this process is a reload replacement (REPOOS_RELOAD=1): retry
8
+ * EADDRINUSE until the old process releases the port, instead of failing.
9
+ */
10
+ reloadReplacement?: boolean;
11
+ /**
12
+ * Force auth off for this instance regardless of [auth] in repoos.toml.
13
+ * For ephemeral in-process servers (the UI smoke gate) that test generic
14
+ * rendering, not auth flows — a project with real auth enabled must not
15
+ * make `repoos check` itself unable to reach the dashboard.
16
+ */
17
+ disableAuth?: boolean;
18
+ /**
19
+ * Fired synchronously the instant the HTTP listener actually binds
20
+ * (`server.listen()`'s own callback), with the live index instance at that
21
+ * exact moment. Exists so a test can assert a STATE invariant instead of a
22
+ * timing one — see boot-timing.test.ts: comparing wall-clock timestamps
23
+ * (even in-process ones) can't reliably distinguish "genuinely concurrent"
24
+ * from "coincidentally fast" when the index build finishes within the same
25
+ * millisecond as listen() on a healthy/fast machine. `index.snapshot()`
26
+ * still reporting zero tasks at this instant is unambiguous regardless of
27
+ * speed: `refreshAllAsync()` only populates the index in one atomic swap
28
+ * at the end, so 0 here can only mean the listener bound before the async
29
+ * build touched anything — a real regression to the old synchronous boot
30
+ * (index built to completion, then listen()) would show the full count
31
+ * already present.
32
+ */
33
+ onListening?: (index: LiveIndex) => void;
34
+ }
35
+ /**
36
+ * Only a long-lived control-plane server may sweep machine-wide serve
37
+ * processes. Preview children deliberately run the same CLI on an ephemeral
38
+ * port, but must never classify their parent control plane (often detached
39
+ * with PPID 1 after a nohup/reload handoff) as an orphan and terminate it.
40
+ * Likewise, in-process test servers use port 0 and are never supervisors.
41
+ */
42
+ export declare function shouldReapStrayServeProcesses(opts: Pick<ServeOptions, "port">, env?: NodeJS.ProcessEnv): boolean;
43
+ export interface ServerHandle {
44
+ url: string;
45
+ port: number;
46
+ close: (reason?: string) => Promise<void>;
47
+ index: LiveIndex;
48
+ }
49
+ export declare function startServer(opts?: ServeOptions): Promise<ServerHandle>;