@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,53 @@
1
+ export interface PreviewServer {
2
+ close: () => void;
3
+ url: string;
4
+ }
5
+ /** Structural subset of the Playwright WebKit API both callers use. */
6
+ export interface SmokeConsoleMessage {
7
+ type(): string;
8
+ text(): string;
9
+ }
10
+ export interface SmokePage {
11
+ on(event: "console", handler: (msg: SmokeConsoleMessage) => void): void;
12
+ on(event: "pageerror", handler: (err: Error) => void): void;
13
+ goto(url: string, options: {
14
+ waitUntil: string;
15
+ timeout: number;
16
+ }): Promise<unknown>;
17
+ title(): Promise<string>;
18
+ evaluate<R>(fn: () => R): Promise<R>;
19
+ $(selector: string): Promise<unknown>;
20
+ waitForTimeout(ms: number): Promise<void>;
21
+ }
22
+ export interface SmokeBrowser {
23
+ newPage(): Promise<SmokePage>;
24
+ newPage(options: {
25
+ viewport: {
26
+ width: number;
27
+ height: number;
28
+ };
29
+ }): Promise<SmokePage>;
30
+ close(): Promise<void>;
31
+ }
32
+ export interface SmokePlaywright {
33
+ webkit: {
34
+ launch(options: {
35
+ headless: boolean;
36
+ }): Promise<SmokeBrowser>;
37
+ };
38
+ }
39
+ /**
40
+ * Start the built UI's server on an ephemeral port so the gate works even when
41
+ * a `repoos serve` instance is already running on the default port. `root` is
42
+ * optional — both callers pass a throwaway fixture root for determinism: the
43
+ * smoke test (check.ts) boots against a bare empty work/ + minimal repoos.toml
44
+ * so it never touches the live board's jobs or preview auto-launch (#0260),
45
+ * and the screenshot script serves a fixture copy.
46
+ */
47
+ export declare function startPreviewServer(root?: string): Promise<PreviewServer>;
48
+ /**
49
+ * Resolve `@playwright/test` and launch headless WebKit. Throws a descriptive
50
+ * error when the package isn't installed so callers can report it as a
51
+ * graceful skip rather than a gate failure.
52
+ */
53
+ export declare function launchWebkit(): Promise<SmokeBrowser>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared headless-UI setup for the two places that start the built app's
3
+ * ephemeral HTTP server and a WebKit browser against it:
4
+ * - `runUISmokeTest` in src/commands/check.ts (`repoos check`'s UI gate)
5
+ * - `scripts/capture-screenshots.mjs` (`bun run screenshots`)
6
+ *
7
+ * Both previously hand-rolled the same "start server on an ephemeral port via
8
+ * createRequire + launch headless WebKit" boilerplate, each with its own copy
9
+ * of the `@playwright/test` / server wiring — so close-out ended up with two
10
+ * independent browser+server launch cycles to verify the same built UI.
11
+ *
12
+ * They run in separate OS processes that are never alive at the same time —
13
+ * `repoos check` is a subprocess of the close-out gate, while screenshots are
14
+ * an on-demand `bun run screenshots` run that, per #0140, is never part of a
15
+ * close-out — so each still performs its own launch at runtime. A literal
16
+ * single shared server + single browser *instance* across that boundary is
17
+ * therefore impossible without folding screenshots into `repoos check` (which
18
+ * would contradict #0140), so the shared logic itself is the intended AC3
19
+ * scope-down (task #0213): one launch implementation, zero drift between the
20
+ * two call sites.
21
+ */
22
+ import { createRequire } from "node:module";
23
+ /**
24
+ * Start the built UI's server on an ephemeral port so the gate works even when
25
+ * a `repoos serve` instance is already running on the default port. `root` is
26
+ * optional — both callers pass a throwaway fixture root for determinism: the
27
+ * smoke test (check.ts) boots against a bare empty work/ + minimal repoos.toml
28
+ * so it never touches the live board's jobs or preview auto-launch (#0260),
29
+ * and the screenshot script serves a fixture copy.
30
+ */
31
+ export async function startPreviewServer(root) {
32
+ const { startServer } = await import("../server/server.js");
33
+ // disableAuth: the smoke gate tests generic rendering (title, board,
34
+ // buttons), not auth flows — a project with [auth] enabled must not make
35
+ // `repoos check` itself unable to reach the dashboard.
36
+ const opts = { host: "127.0.0.1", port: 0, disableAuth: true };
37
+ if (root !== undefined)
38
+ opts.root = root;
39
+ return startServer(opts);
40
+ }
41
+ /**
42
+ * Resolve `@playwright/test` and launch headless WebKit. Throws a descriptive
43
+ * error when the package isn't installed so callers can report it as a
44
+ * graceful skip rather than a gate failure.
45
+ */
46
+ export async function launchWebkit() {
47
+ // @playwright/test is a CJS package. Bun's ESM `import()` of it resolves the
48
+ // named browser exports to `undefined` (root cause of #0200), so load it via
49
+ // createRequire, which handles the CJS interop under both Bun and Node.
50
+ // Types are structural (Smoke*) rather than `typeof import("@playwright/test")`
51
+ // so `tsc` compiles even when the package is absent — the build must not fail
52
+ // before the "not installed" skip can run.
53
+ const require = createRequire(import.meta.url);
54
+ let playwright;
55
+ try {
56
+ playwright = require("@playwright/test");
57
+ }
58
+ catch {
59
+ throw new Error("Cannot find module @playwright/test (not installed)");
60
+ }
61
+ return playwright.webkit.launch({ headless: true });
62
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Run the smoke test with the same outcomes `repoos check` used to apply
3
+ * in-process: pass → 0, Playwright/WebKit unavailable → skip (0), anything
4
+ * else → 1. Returns the exit code so the caller decides how to exit.
5
+ */
6
+ export declare function cmdUISmoke(): Promise<number>;
@@ -0,0 +1,220 @@
1
+ /**
2
+ * RepoOS's own headless UI smoke test (#0348).
3
+ *
4
+ * `repoos check`'s ui-smoke step is per-project and opt-in: it runs whatever a
5
+ * project declares (a `smoke` package.json script, or `[check] uiSmoke` in
6
+ * repoos.toml). RepoOS dogfoods that mechanism instead of keeping a
7
+ * RepoOS-only branch in check.ts: its own `smoke` script (scripts/ui-smoke.mjs)
8
+ * calls `cmdUISmoke()` below against the freshly built dist/.
9
+ *
10
+ * Server startup + webkit launch share the harness in ui-harness.ts with the
11
+ * screenshot script (#0213).
12
+ */
13
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
14
+ import { tmpdir } from "node:os";
15
+ import { join } from "node:path";
16
+ import { c } from "../cli/colors.js";
17
+ import { startPreviewServer, launchWebkit } from "./ui-harness.js";
18
+ /**
19
+ * Build a throwaway, empty fixture repo to serve the built SPA against.
20
+ * The smoke test only cares that the built UI renders with zero console errors,
21
+ * so booting it against the live checkout's real board drags in job recovery
22
+ * and preview auto-launch reconciliation for every active/review task (0260).
23
+ * A bare `work/` + minimal `repoos.toml` avoids all of that: no tasks, no
24
+ * recovery, no auto-launch — constant cost regardless of board size.
25
+ */
26
+ function makeSmokeFixture() {
27
+ const root = mkdtempSync(join(tmpdir(), "repoos-smoke-"));
28
+ mkdirSync(join(root, "work"), { recursive: true });
29
+ writeFileSync(join(root, "repoos.toml"), 'theme = "dark"\nuiTheme = "classic"\n\n');
30
+ return root;
31
+ }
32
+ /**
33
+ * Start the dev server, run Playwright WebKit smoke tests, then stop.
34
+ * Exports failures as thrown errors. Server startup + webkit launch share the
35
+ * harness in ui-harness.ts with the screenshot script (#0213).
36
+ */
37
+ async function runUISmokeTest() {
38
+ const fixture = makeSmokeFixture();
39
+ let server;
40
+ try {
41
+ server = await startPreviewServer(fixture);
42
+ }
43
+ catch (err) {
44
+ rmSync(fixture, { recursive: true, force: true });
45
+ throw err;
46
+ }
47
+ let browser;
48
+ try {
49
+ browser = await launchWebkit();
50
+ }
51
+ catch (err) {
52
+ server.close();
53
+ rmSync(fixture, { recursive: true, force: true });
54
+ throw err;
55
+ }
56
+ try {
57
+ const page = await browser.newPage();
58
+ const consoleErrs = [];
59
+ const pageErrors = [];
60
+ page.on("console", (msg) => {
61
+ if (msg.type() === "error")
62
+ consoleErrs.push(msg.text());
63
+ });
64
+ page.on("pageerror", (err) => {
65
+ pageErrors.push(err.message);
66
+ });
67
+ await page.goto(server.url, { waitUntil: "load", timeout: 20_000 });
68
+ // Check page title is correct
69
+ const title = await page.title();
70
+ if (title !== "RepoOS")
71
+ throw new Error(`Unexpected title: "${title}"`);
72
+ // Verify we are testing the built Vite SPA, which references hashed
73
+ // assets in /assets/.
74
+ const hashedAsset = await page.evaluate(() => {
75
+ const scripts = Array.from(document.querySelectorAll("script[src]"));
76
+ return scripts.some((s) => (s.getAttribute("src") ?? "").startsWith("/assets/"));
77
+ });
78
+ if (!hashedAsset) {
79
+ throw new Error("Served page is not the built Vite app (no /assets/ bundle)");
80
+ }
81
+ // Check that the app MOUNTED — no unrendered mustache in the DOM
82
+ const bodyText = await page.evaluate(() => document.body.innerText);
83
+ if (bodyText.includes("{{") || bodyText.includes("}}")) {
84
+ throw new Error("Unrendered mustache found in DOM — Vue did not mount");
85
+ }
86
+ // Check that a known root element rendered with real content
87
+ const appEl = await page.$("#app");
88
+ if (!appEl)
89
+ throw new Error("#app element not found");
90
+ const hasBrand = await page.evaluate(() => document.body.innerText.includes("RepoOS"));
91
+ if (!hasBrand)
92
+ throw new Error('Expected "RepoOS" in rendered content');
93
+ // Navigate to work page and click +New Task
94
+ await page.evaluate(() => {
95
+ const navItems = document.querySelectorAll(".nav-item");
96
+ for (const item of Array.from(navItems)) {
97
+ if (item.textContent?.includes("Work"))
98
+ item.click();
99
+ }
100
+ });
101
+ await page.waitForTimeout(500);
102
+ // Verify work page rendered
103
+ const workEl = await page.$(".board");
104
+ if (!workEl) {
105
+ consoleErrs.push("Work page board not rendered — check page navigation");
106
+ }
107
+ // Check that the +New Task button exists
108
+ const newBtn = await page.$(".new-btn");
109
+ if (!newBtn) {
110
+ consoleErrs.push("+New Task button not found in DOM");
111
+ }
112
+ // ── CSS regression guard: utility spacing must actually apply ─────
113
+ // Tailwind v4 emits all its CSS inside cascade layers. If an
114
+ // UNLAYERED reset such as `*{padding:0;margin:0}` is ever added to
115
+ // style.css, it silently beats every spacing utility (unlayered rules
116
+ // take precedence over @layer rules), collapsing padding on shadcn
117
+ // controls while console stays clean. Flag any non-explicit-zero
118
+ // spacing utility whose computed value is 0.
119
+ const assertUtilitySpacing = async (where) => {
120
+ const offenders = await page.evaluate(() => {
121
+ const AXIS = {
122
+ p: ["paddingTop", "paddingRight", "paddingBottom", "paddingLeft"],
123
+ px: ["paddingLeft", "paddingRight"],
124
+ py: ["paddingTop", "paddingBottom"],
125
+ pt: ["paddingTop"],
126
+ pr: ["paddingRight"],
127
+ pb: ["paddingBottom"],
128
+ pl: ["paddingLeft"],
129
+ m: ["marginTop", "marginRight", "marginBottom", "marginLeft"],
130
+ mx: ["marginLeft", "marginRight"],
131
+ my: ["marginTop", "marginBottom"],
132
+ mt: ["marginTop"],
133
+ mr: ["marginRight"],
134
+ mb: ["marginBottom"],
135
+ ml: ["marginLeft"],
136
+ };
137
+ const bad = [];
138
+ for (const el of Array.from(document.querySelectorAll("*"))) {
139
+ if (!(el instanceof HTMLElement))
140
+ continue;
141
+ const s = getComputedStyle(el);
142
+ for (const cls of el.classList) {
143
+ if (cls.startsWith("-"))
144
+ continue; // negative margins are intentional
145
+ const m = /^([pm])([trblxy]?)-(?:\[)?([1-9])/.exec(cls);
146
+ if (!m)
147
+ continue;
148
+ for (const prop of AXIS[m[1] + m[2]] ?? []) {
149
+ if (parseFloat(s[prop]) <= 0) {
150
+ bad.push(`${cls} → ${prop} = ${s[prop]} on <${el.tagName.toLowerCase()}>`);
151
+ break;
152
+ }
153
+ }
154
+ }
155
+ }
156
+ return [...new Set(bad)];
157
+ });
158
+ if (offenders.length > 0) {
159
+ throw new Error("Utility spacing collapsed on " + where + ": " + offenders.slice(0, 6).join("; "));
160
+ }
161
+ };
162
+ await assertUtilitySpacing("dashboard");
163
+ // Re-run the guard on the settings page (covers shadcn Button + Select)
164
+ await page.evaluate(() => {
165
+ const navItems = document.querySelectorAll(".nav-item");
166
+ for (const item of Array.from(navItems)) {
167
+ if (item.textContent?.includes("Settings"))
168
+ item.click();
169
+ }
170
+ });
171
+ await page.waitForTimeout(500);
172
+ await assertUtilitySpacing("settings");
173
+ // Check for zero console errors
174
+ if (consoleErrs.length > 0) {
175
+ let msg = "Console errors (" + consoleErrs.length + "): " + consoleErrs.join("; ");
176
+ if (pageErrors.length > 0)
177
+ msg += " | Page errors: " + pageErrors.join("; ");
178
+ throw new Error(msg);
179
+ }
180
+ if (pageErrors.length > 0) {
181
+ throw new Error("Page errors (" + pageErrors.length + "): " + pageErrors.join("; "));
182
+ }
183
+ }
184
+ finally {
185
+ if (browser)
186
+ await browser.close();
187
+ server.close();
188
+ rmSync(fixture, { recursive: true, force: true });
189
+ }
190
+ }
191
+ /** A missing @playwright/test install or WebKit binary — a skip, not a failure. */
192
+ function isPlaywrightUnavailable(msg) {
193
+ return (msg.includes("Cannot find module") ||
194
+ msg.includes("not installed") ||
195
+ msg.includes("Executable doesn't exist"));
196
+ }
197
+ /**
198
+ * Run the smoke test with the same outcomes `repoos check` used to apply
199
+ * in-process: pass → 0, Playwright/WebKit unavailable → skip (0), anything
200
+ * else → 1. Returns the exit code so the caller decides how to exit.
201
+ */
202
+ export async function cmdUISmoke() {
203
+ try {
204
+ await runUISmokeTest();
205
+ console.log(c.green(" ✔ UI smoke test passed"));
206
+ return 0;
207
+ }
208
+ catch (e) {
209
+ const msg = e.message;
210
+ if (isPlaywrightUnavailable(msg)) {
211
+ console.log(c.dim(" · Playwright not available — UI smoke test skipped"));
212
+ console.log(c.dim(" Install: bun add -d @playwright/test && bunx playwright install webkit"));
213
+ return 0;
214
+ }
215
+ console.log(c.red(" ✗ UI smoke test failed: " + msg.split("\n")[0]));
216
+ if (msg.includes("\n"))
217
+ console.log(c.dim(msg));
218
+ return 1;
219
+ }
220
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The release notes to print after an upgrade, or null when there's nothing
3
+ * to show — GitHub returns `body` as `null`/absent for a release cut with an
4
+ * empty notes field (#0361's UI leaves the field optional), and this must
5
+ * stay silent then, not print an empty line or "no notes available" filler.
6
+ */
7
+ export declare function releaseNotesToPrint(body: string | null | undefined): string | null;
8
+ export declare function cmdUpgrade(args: string[]): Promise<void>;
9
+ /**
10
+ * The `repoos` launcher script: Bun when it's installed, Node otherwise
11
+ * (`REPOOS_RUNTIME=node` pins Node). The runtime is picked each time `repoos`
12
+ * runs, so installing Bun later takes effect with no reinstall. Must match the
13
+ * heredoc in install.sh exactly; launcher.test.ts compares the two.
14
+ */
15
+ export declare function launcherScript(entry: string): string;
@@ -0,0 +1,188 @@
1
+ /**
2
+ * `repoos upgrade` — self-update for standalone (curl-installed) builds.
3
+ * Downloads the latest GitHub release's dist tarball and swaps it into place.
4
+ *
5
+ * Package-manager installs (npm/bun, living under node_modules/) are not
6
+ * touched here — those update through the package manager itself.
7
+ */
8
+ import { execFileSync } from "node:child_process";
9
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import { dirname, join } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import { c } from "../cli/colors.js";
14
+ const REPO = "repo-os/repoos";
15
+ /** The directory containing cli/, core/, server/, ui/, .build-info.json — dist/ in a source checkout, or the whole install root for a standalone install. */
16
+ function installRoot() {
17
+ return dirname(dirname(fileURLToPath(import.meta.url)));
18
+ }
19
+ function readVersion(root) {
20
+ try {
21
+ const info = JSON.parse(readFileSync(join(root, ".build-info.json"), "utf8"));
22
+ return info.version ?? null;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ /**
29
+ * The release notes to print after an upgrade, or null when there's nothing
30
+ * to show — GitHub returns `body` as `null`/absent for a release cut with an
31
+ * empty notes field (#0361's UI leaves the field optional), and this must
32
+ * stay silent then, not print an empty line or "no notes available" filler.
33
+ */
34
+ export function releaseNotesToPrint(body) {
35
+ const trimmed = body?.trim();
36
+ return trimmed ? trimmed : null;
37
+ }
38
+ /** `--channel beta|canary|rc` from argv, or null for the default stable channel. */
39
+ function parseChannel(args) {
40
+ const flag = args.indexOf("--channel");
41
+ const value = flag !== -1 ? args[flag + 1] : undefined;
42
+ return value && !value.startsWith("--") ? value : null;
43
+ }
44
+ /**
45
+ * `GET /releases/latest` always excludes prereleases (GitHub's own rule, not
46
+ * configurable) — release.yml marks any tag with a "-" (v0.6.0-beta.1,
47
+ * -canary.N, -rc.N) as a prerelease, exactly so stable users never get handed
48
+ * one from this endpoint. A channel opt-in has to use the list endpoint
49
+ * instead and find its own match.
50
+ */
51
+ async function fetchLatestRelease(channel) {
52
+ if (!channel) {
53
+ const res = await fetch(`https://api.github.com/repos/${REPO}/releases/latest`);
54
+ if (!res.ok)
55
+ throw new Error(`GitHub API returned ${res.status}`);
56
+ return (await res.json());
57
+ }
58
+ // Newest first by default; the first tag matching "-<channel>." wins.
59
+ const res = await fetch(`https://api.github.com/repos/${REPO}/releases?per_page=30`);
60
+ if (!res.ok)
61
+ throw new Error(`GitHub API returned ${res.status}`);
62
+ const releases = (await res.json());
63
+ const match = releases.find((r) => r.tag_name.includes(`-${channel}.`));
64
+ if (!match)
65
+ throw new Error(`No "${channel}" release found in the last 30 releases.`);
66
+ return match;
67
+ }
68
+ export async function cmdUpgrade(args) {
69
+ const root = installRoot();
70
+ const channel = parseChannel(args);
71
+ if (root.includes("node_modules")) {
72
+ console.log(c.yellow(" repoos was installed via a package manager."));
73
+ console.log(c.dim(" Update it the same way:"));
74
+ console.log(c.dim(" bun update -g @repo-os/repoos") +
75
+ c.dim(" or ") +
76
+ c.dim("npm update -g @repo-os/repoos"));
77
+ return;
78
+ }
79
+ const current = readVersion(root);
80
+ if (!current) {
81
+ console.log(c.yellow(" repoos appears to be running from a source checkout, not a standalone install."));
82
+ console.log(c.dim(" Update it with: git pull && bun run build"));
83
+ return;
84
+ }
85
+ console.log(c.dim(` Current version: v${current}`));
86
+ console.log(c.dim(channel ? ` Checking latest "${channel}" release…` : " Checking latest release…"));
87
+ let release;
88
+ try {
89
+ release = await fetchLatestRelease(channel);
90
+ }
91
+ catch (e) {
92
+ console.error(c.red(" Failed to check for updates: " + e.message));
93
+ process.exitCode = 1;
94
+ return;
95
+ }
96
+ const latest = release.tag_name.replace(/^v/, "");
97
+ if (latest === current) {
98
+ console.log(c.green(` Already up to date (v${current}).`));
99
+ return;
100
+ }
101
+ const asset = release.assets.find((a) => a.name === "repoos-dist.tar.gz");
102
+ if (!asset) {
103
+ console.error(c.red(` No repoos-dist.tar.gz asset found on release v${latest}.`));
104
+ process.exitCode = 1;
105
+ return;
106
+ }
107
+ console.log(c.dim(` Upgrading v${current} → v${latest}…`));
108
+ // Do all the work in siblings of the install root, never in the system temp
109
+ // dir: `/tmp` is often a small tmpfs (or has a per-user quota — Omarchy sets
110
+ // one), and a multi-MB download there fails with `curl: (23)`. Siblings of
111
+ // `root` are on the same filesystem as the install, so there's space and the
112
+ // final swap is a plain rename.
113
+ const work = `${root}.upgrade-download`;
114
+ const staged = `${root}.upgrade-staged`;
115
+ const displaced = `${root}.upgrade-old`;
116
+ for (const dir of [work, staged, displaced]) {
117
+ if (existsSync(dir))
118
+ rmSync(dir, { recursive: true, force: true });
119
+ }
120
+ mkdirSync(work, { recursive: true });
121
+ const tmpTar = join(work, "repoos-dist.tar.gz");
122
+ try {
123
+ execFileSync("curl", ["-fsSL", asset.browser_download_url, "-o", tmpTar], { stdio: "inherit" });
124
+ mkdirSync(staged, { recursive: true });
125
+ execFileSync("tar", ["-xzf", tmpTar, "-C", staged]);
126
+ execFileSync("chmod", ["+x", join(staged, "cli", "index.js")]);
127
+ renameSync(root, displaced);
128
+ try {
129
+ renameSync(staged, root);
130
+ }
131
+ catch (e) {
132
+ renameSync(displaced, root);
133
+ throw e;
134
+ }
135
+ rmSync(displaced, { recursive: true, force: true });
136
+ }
137
+ finally {
138
+ rmSync(work, { recursive: true, force: true });
139
+ if (existsSync(staged))
140
+ rmSync(staged, { recursive: true, force: true });
141
+ }
142
+ regenerateLauncher(root);
143
+ console.log(c.green(` Upgraded to v${latest}.`));
144
+ const notes = releaseNotesToPrint(release.body);
145
+ if (notes) {
146
+ console.log("");
147
+ console.log(notes);
148
+ }
149
+ }
150
+ /**
151
+ * The `repoos` launcher script: Bun when it's installed, Node otherwise
152
+ * (`REPOOS_RUNTIME=node` pins Node). The runtime is picked each time `repoos`
153
+ * runs, so installing Bun later takes effect with no reinstall. Must match the
154
+ * heredoc in install.sh exactly; launcher.test.ts compares the two.
155
+ */
156
+ export function launcherScript(entry) {
157
+ return [
158
+ "#!/usr/bin/env bash",
159
+ "# repoos launcher: Bun when it's installed, Node otherwise (REPOOS_RUNTIME=node pins Node).",
160
+ `entry="${entry}"`,
161
+ 'if [ "${REPOOS_RUNTIME:-}" != "node" ]; then',
162
+ ' bun="${REPOOS_BUN_PATH:-$(command -v bun 2>/dev/null || true)}"',
163
+ ' if [ -n "$bun" ] && [ -x "$bun" ]; then exec "$bun" "$entry" "$@"; fi',
164
+ "fi",
165
+ 'exec node --no-warnings "$entry" "$@"',
166
+ "",
167
+ ].join("\n");
168
+ }
169
+ /**
170
+ * Rewrite the `repoos` launcher script install.sh created, so an existing
171
+ * curl install picks up launcher-level fixes (e.g. the Bun-first runtime
172
+ * choice) without needing to re-run install.sh. Silent
173
+ * no-op if the launcher isn't where install.sh puts it — e.g. a custom setup
174
+ * that symlinks straight to cli/index.js instead.
175
+ */
176
+ function regenerateLauncher(root) {
177
+ const binDir = process.env.REPOOS_BIN_DIR || join(homedir(), ".local", "bin");
178
+ const launcherPath = join(binDir, "repoos");
179
+ if (!existsSync(launcherPath))
180
+ return;
181
+ try {
182
+ writeFileSync(launcherPath, launcherScript(join(root, "cli", "index.js")));
183
+ chmodSync(launcherPath, 0o755);
184
+ }
185
+ catch {
186
+ // Best-effort — an upgrade that fails to touch the launcher isn't worth failing over.
187
+ }
188
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Auth persistence layer. Wraps the SQLite database with typed operations
3
+ * for users, sessions, OTP challenges, and audit log entries.
4
+ *
5
+ * All OTP codes and session tokens are stored hashed — plaintext never
6
+ * touches disk.
7
+ */
8
+ import type { AuthRole } from "./auth.js";
9
+ export interface AuthUser {
10
+ email: string;
11
+ role: AuthRole;
12
+ displayName: string | null;
13
+ authSource: string;
14
+ addedBy: string | null;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ }
18
+ export interface AuthSessionRow {
19
+ sessionId: string;
20
+ tokenHash: string;
21
+ email: string;
22
+ role: AuthRole;
23
+ createdAt: string;
24
+ expiresAt: string;
25
+ revokedAt: string | null;
26
+ }
27
+ export interface OtpChallengeRow {
28
+ id: number;
29
+ email: string;
30
+ codeHash: string;
31
+ createdAt: string;
32
+ expiresAt: string;
33
+ usedAt: string | null;
34
+ sourceIp: string | null;
35
+ }
36
+ export interface AuditLogEntry {
37
+ id: number;
38
+ action: string;
39
+ targetEmail: string | null;
40
+ actorEmail: string | null;
41
+ details: string | null;
42
+ createdAt: string;
43
+ }
44
+ export declare class AuthStore {
45
+ private db;
46
+ private available;
47
+ constructor(repoRoot: string);
48
+ isAvailable(): boolean;
49
+ getUser(email: string): AuthUser | null;
50
+ listUsers(): AuthUser[];
51
+ upsertUser(email: string, role: AuthRole, addedBy: string | null, displayName?: string): void;
52
+ deleteUser(email: string): boolean;
53
+ getAdminCount(): number;
54
+ createSession(email: string, role: AuthRole, maxAgeSeconds: number): string;
55
+ getSession(token: string): AuthSessionRow | null;
56
+ revokeSession(token: string): boolean;
57
+ revokeAllSessions(email: string): number;
58
+ /** Update the role column on all active sessions for a user. */
59
+ updateSessionRoles(email: string, newRole: AuthRole): number;
60
+ cleanupExpiredSessions(): number;
61
+ /** Store a hashed OTP challenge. Returns the challenge id. */
62
+ createOtpChallenge(email: string, codeHash: string, ttlSeconds: number, sourceIp: string | null): number;
63
+ /** Find a valid, unused OTP for this email. Returns null if none found or expired. */
64
+ findValidOtp(email: string, codeHash: string): OtpChallengeRow | null;
65
+ /** Mark an OTP as used. */
66
+ markOtpUsed(otpId: number): void;
67
+ /** Count OTP requests for this email in the given time window. */
68
+ countRecentOtpRequests(email: string, windowSeconds: number): number;
69
+ /** Count failed verify attempts for this email in the given time window. */
70
+ countFailedVerifyAttempts(email: string, windowSeconds: number): number;
71
+ cleanupExpiredOtps(): number;
72
+ logAudit(action: string, targetEmail: string | null, actorEmail: string | null, details?: string): void;
73
+ getAuditLog(limit?: number): AuditLogEntry[];
74
+ private toUser;
75
+ private toSession;
76
+ private toOtp;
77
+ private toAuditEntry;
78
+ close(): void;
79
+ }
80
+ export declare function getAuthStore(repoRoot: string): AuthStore | null;
81
+ export declare function resetAuthStoreInstance(): void;