@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,119 @@
1
+ import type { DeploymentConfig, RepoOSConfig } from "../core/types.js";
2
+ export interface DeploymentRow {
3
+ name: string;
4
+ /** Groups this row with others of the same service across branches (#0365). Defaults to `name`. */
5
+ service: string;
6
+ branch: string;
7
+ /** Plain provider label from config (e.g. "cloudflare-workers"). */
8
+ provider: string | null;
9
+ /** The live URL — the row's primary link. */
10
+ url: string | null;
11
+ /** Optional provider-dashboard URL, also rendered as a link when present. */
12
+ dashboardUrl: string | null;
13
+ /** Subdirectory the freshness lookup was scoped to, when configured. */
14
+ subdir: string | null;
15
+ /** ISO timestamp of the last commit on the branch touching the subdir. */
16
+ lastPushAt: string | null;
17
+ /** Short SHA of that commit. */
18
+ lastPushSha: string | null;
19
+ /**
20
+ * Subdir-scoped version of the branch's `mainSync` ahead/behind counts
21
+ * (#0367): of the commits separating origin/<branch> from local main, how
22
+ * many actually touch THIS row's subdir. Null when no `subdir` is
23
+ * configured (the branch-level count already is this row's scope) or when
24
+ * either ref couldn't be resolved.
25
+ */
26
+ changesVsMain: {
27
+ aheadOfMain: number;
28
+ behindMain: number;
29
+ } | null;
30
+ }
31
+ export interface DeploymentBranch {
32
+ branch: string;
33
+ /** Commits on local <branch> missing from origin/<branch>; null when the remote ref is unknown. */
34
+ ahead: number | null;
35
+ /** Commits on origin/<branch> missing from local <branch>. */
36
+ behind: number | null;
37
+ /** True when origin/<branch> resolves at all. */
38
+ hasOrigin: boolean;
39
+ /** True when the local branch exists (a configured-but-unborn branch can't deploy). */
40
+ localExists: boolean;
41
+ /**
42
+ * When set, "Deploy" fast-forwards this branch to this configured branch
43
+ * before pushing (e.g. prod ← main). Recomputed from actual git ancestry —
44
+ * a branch equal to its neighbor (just deployed) drops back to a plain push.
45
+ */
46
+ ffFrom: string | null;
47
+ /**
48
+ * Where the DEPLOYED ref (`origin/<branch>`) stands relative to the LOCAL
49
+ * `main` branch (#0365) — the headline sync metric, replacing the raw
50
+ * ahead/behind-vs-own-origin chips. "same": origin/<branch> == local main.
51
+ * "behind": origin/<branch> is a strict ancestor of local main (deploying
52
+ * would fast-forward it up to date — see the `ffFrom` badge). "ahead":
53
+ * local main is a strict ancestor of origin/<branch> (the deployed ref has
54
+ * commits local main lacks — unusual, e.g. a hotfix landed directly on this
55
+ * branch). "diverged": neither is an ancestor of the other. "unknown": no
56
+ * origin/<branch>, or no local `main` ref to compare against.
57
+ */
58
+ mainSync: {
59
+ state: "same" | "behind" | "ahead" | "diverged" | "unknown";
60
+ /** Commits on origin/<branch> missing from local main (0 unless "ahead"/"diverged"). */
61
+ aheadOfMain: number;
62
+ /** Commits on local main missing from origin/<branch> (0 unless "behind"/"diverged"). */
63
+ behindMain: number;
64
+ };
65
+ }
66
+ export interface DeploymentsStatus {
67
+ enabled: boolean;
68
+ rows: DeploymentRow[];
69
+ branches: DeploymentBranch[];
70
+ /** Main checkout the git state was read from (a preview worktree resolves here). */
71
+ root: string | null;
72
+ /** Uncommitted changes in the main checkout — blocks every deploy. */
73
+ dirty: boolean;
74
+ /** Branch the main checkout is currently on (informational). */
75
+ currentBranch: string | null;
76
+ }
77
+ export interface DeployResult {
78
+ ok: boolean;
79
+ output: string;
80
+ }
81
+ interface CommandResult {
82
+ code: number | null;
83
+ stdout: string;
84
+ stderr: string;
85
+ error?: Error;
86
+ }
87
+ export type DeployCommandRunner = (command: string, args: string[], cwd: string, timeout?: number) => Promise<CommandResult>;
88
+ export declare function captureOutput(stdout: string, stderr: string): string;
89
+ export declare function configuredDeployments(config: RepoOSConfig): DeploymentConfig[];
90
+ /**
91
+ * The checkout deploys run against: the MAIN checkout, even when the server is
92
+ * serving a task preview from a linked worktree — branch refs are shared
93
+ * across worktrees, but dirty-state and branch-health belong to the checkout
94
+ * the user actually manages (same resolution rule as board reads, #0068).
95
+ */
96
+ export declare function deployRoot(config: RepoOSConfig): string;
97
+ /** Distinct configured branches, in first-appearance order. */
98
+ export declare function deploymentBranches(rows: DeploymentConfig[]): string[];
99
+ /**
100
+ * Nearest configured branch that this branch can be fast-forwarded to: a
101
+ * strict ancestor relationship (branch behind, never diverged), closest first.
102
+ * Derived entirely from actual topology + config — no main/prod constants, so
103
+ * a repo with differently named (or more than two) branches gets the right
104
+ * pairing. Returns null when the branch should just be pushed as-is.
105
+ */
106
+ export declare function fastForwardSource(exec: DeployCommandRunner, branch: string, branches: string[], cwd: string): Promise<string | null>;
107
+ export declare function getDeploymentsStatus(config: RepoOSConfig, exec?: DeployCommandRunner): Promise<DeploymentsStatus>;
108
+ /**
109
+ * Deploy one branch: a plain `git push origin <branch>`, or — when the branch
110
+ * is strictly behind another configured branch (prod behind main) — a
111
+ * fast-forward of the local ref first, then the push. The fast-forward uses
112
+ * `git merge --ff-only <src>` when the checkout is ON that branch (git refuses
113
+ * to fetch into a checked-out branch) and `git fetch . <src>:<branch>` — which
114
+ * git itself refuses on non-fast-forward — otherwise. There is no code path
115
+ * that pushes with --force: every non-fast-forward case fails loudly with
116
+ * git's own refusal in the output.
117
+ */
118
+ export declare function deployBranch(config: RepoOSConfig, branch: string, exec?: DeployCommandRunner): Promise<DeployResult>;
119
+ export {};
@@ -0,0 +1,325 @@
1
+ /**
2
+ * Deployments status + push actions (#0340).
3
+ *
4
+ * Where `release.ts` models one versioned artifact, this module models the
5
+ * grid of configured [[deployments]] rows (service × branch) and the shared
6
+ * branch state behind them. Everything here is plain git against the already-
7
+ * configured `origin` remote — no provider API calls, no new credentials.
8
+ * Cloudflare (or any git-connected host) rebuilds from the push; whether that
9
+ * build succeeded is deliberately out of scope for v1.
10
+ */
11
+ import { spawn } from "node:child_process";
12
+ import { mainCheckoutRoot } from "../core/config.js";
13
+ export function captureOutput(stdout, stderr) {
14
+ return [stdout.trim(), stderr.trim()].filter(Boolean).join("\n");
15
+ }
16
+ const run = (command, args, cwd, timeout = 30_000) => new Promise((resolveRun) => {
17
+ const child = spawn(command, args, { cwd, env: process.env });
18
+ let stdout = "";
19
+ let stderr = "";
20
+ let settled = false;
21
+ const finish = (code, error) => {
22
+ if (settled)
23
+ return;
24
+ settled = true;
25
+ clearTimeout(timer);
26
+ resolveRun({ code, stdout, stderr, error });
27
+ };
28
+ child.stdout.on("data", (data) => (stdout += data.toString("utf8")));
29
+ child.stderr.on("data", (data) => (stderr += data.toString("utf8")));
30
+ child.on("error", (error) => finish(null, error));
31
+ child.on("close", (code) => finish(code));
32
+ const timer = setTimeout(() => child.kill("SIGKILL"), timeout);
33
+ });
34
+ export function configuredDeployments(config) {
35
+ return Array.isArray(config.deployments) ? config.deployments : [];
36
+ }
37
+ /**
38
+ * The checkout deploys run against: the MAIN checkout, even when the server is
39
+ * serving a task preview from a linked worktree — branch refs are shared
40
+ * across worktrees, but dirty-state and branch-health belong to the checkout
41
+ * the user actually manages (same resolution rule as board reads, #0068).
42
+ */
43
+ export function deployRoot(config) {
44
+ return mainCheckoutRoot(config.root) ?? config.root;
45
+ }
46
+ /** Distinct configured branches, in first-appearance order. */
47
+ export function deploymentBranches(rows) {
48
+ const seen = [];
49
+ for (const row of rows)
50
+ if (!seen.includes(row.branch))
51
+ seen.push(row.branch);
52
+ return seen;
53
+ }
54
+ function cmd(exec, args, cwd, timeout) {
55
+ return exec("git", args, cwd, timeout);
56
+ }
57
+ /**
58
+ * The local branch every deployment target's sync status is measured against
59
+ * (#0365) — this repo's (and most repos') trunk, matching the same "main"
60
+ * assumption `release.ts` already makes for cutting a release. Not sourced
61
+ * from config: making this configurable is real scope this task explicitly
62
+ * deferred (the user accepted the simplification of comparing every branch,
63
+ * including prod, against local main directly rather than a stricter
64
+ * prod-vs-origin/main chain).
65
+ */
66
+ const SYNC_REFERENCE_BRANCH = "main";
67
+ /**
68
+ * Where `origin/<branch>` (the deployed ref) stands relative to the local
69
+ * `main` branch (#0365) — see `DeploymentBranch.mainSync`.
70
+ */
71
+ async function branchVsMain(exec, branch, cwd) {
72
+ const unknown = { state: "unknown", aheadOfMain: 0, behindMain: 0 };
73
+ const origin = `origin/${branch}`;
74
+ const [originRef, mainRef] = await Promise.all([
75
+ cmd(exec, ["rev-parse", "--verify", "--quiet", origin], cwd),
76
+ cmd(exec, ["rev-parse", "--verify", "--quiet", SYNC_REFERENCE_BRANCH], cwd),
77
+ ]);
78
+ if (originRef.code !== 0 || mainRef.code !== 0)
79
+ return unknown;
80
+ const [aheadRes, behindRes] = await Promise.all([
81
+ cmd(exec, ["rev-list", "--count", `${SYNC_REFERENCE_BRANCH}..${origin}`], cwd),
82
+ cmd(exec, ["rev-list", "--count", `${origin}..${SYNC_REFERENCE_BRANCH}`], cwd),
83
+ ]);
84
+ if (aheadRes.code !== 0 || behindRes.code !== 0)
85
+ return unknown;
86
+ const aheadOfMain = Number(aheadRes.stdout.trim()) || 0;
87
+ const behindMain = Number(behindRes.stdout.trim()) || 0;
88
+ const state = aheadOfMain === 0 && behindMain === 0
89
+ ? "same"
90
+ : aheadOfMain === 0
91
+ ? "behind"
92
+ : behindMain === 0
93
+ ? "ahead"
94
+ : "diverged";
95
+ return { state, aheadOfMain, behindMain };
96
+ }
97
+ /**
98
+ * Same question as `branchVsMain`, scoped to one service's `subdir` (#0367):
99
+ * of the commits separating `origin/<branch>` from local `main`, how many
100
+ * actually touch this subtree? The branch-level count is honestly whole-
101
+ * branch (a repo doing unrelated work between deploys inflates it), which
102
+ * reads as misleading next to a specific service — this answers "does any of
103
+ * that distance actually apply to what I'm looking at."
104
+ *
105
+ * Returns null when there's nothing to scope (no subdir configured — the
106
+ * branch-level count already IS this row's scope) or when either ref can't
107
+ * be resolved (mirrors `branchVsMain`'s "unknown" case without a redundant
108
+ * ref-existence check, since a branch's own `branchVsMain` result already
109
+ * covers that call site).
110
+ */
111
+ async function subdirVsMain(exec, branch, subdir, cwd) {
112
+ if (!subdir)
113
+ return null;
114
+ const origin = `origin/${branch}`;
115
+ const [aheadRes, behindRes] = await Promise.all([
116
+ cmd(exec, ["rev-list", "--count", `${SYNC_REFERENCE_BRANCH}..${origin}`, "--", subdir], cwd),
117
+ cmd(exec, ["rev-list", "--count", `${origin}..${SYNC_REFERENCE_BRANCH}`, "--", subdir], cwd),
118
+ ]);
119
+ if (aheadRes.code !== 0 || behindRes.code !== 0)
120
+ return null;
121
+ return {
122
+ aheadOfMain: Number(aheadRes.stdout.trim()) || 0,
123
+ behindMain: Number(behindRes.stdout.trim()) || 0,
124
+ };
125
+ }
126
+ /**
127
+ * Nearest configured branch that this branch can be fast-forwarded to: a
128
+ * strict ancestor relationship (branch behind, never diverged), closest first.
129
+ * Derived entirely from actual topology + config — no main/prod constants, so
130
+ * a repo with differently named (or more than two) branches gets the right
131
+ * pairing. Returns null when the branch should just be pushed as-is.
132
+ */
133
+ export async function fastForwardSource(exec, branch, branches, cwd) {
134
+ const others = branches.filter((b) => b !== branch);
135
+ if (!others.length)
136
+ return null;
137
+ const sha = await cmd(exec, ["rev-parse", branch], cwd);
138
+ if (sha.code !== 0)
139
+ return null;
140
+ const candidates = [];
141
+ for (const other of others) {
142
+ const otherSha = await cmd(exec, ["rev-parse", other], cwd);
143
+ if (otherSha.code !== 0)
144
+ continue;
145
+ if (otherSha.stdout.trim() === sha.stdout.trim())
146
+ continue; // equal ≠ strict ancestor
147
+ const isAncestor = await cmd(exec, ["merge-base", "--is-ancestor", branch, other], cwd);
148
+ if (isAncestor.code !== 0)
149
+ continue;
150
+ const distance = await cmd(exec, ["rev-list", "--count", `${branch}..${other}`], cwd);
151
+ if (distance.code !== 0)
152
+ continue;
153
+ candidates.push({ branch: other, distance: Number(distance.stdout.trim()) || 0 });
154
+ }
155
+ candidates.sort((a, b) => a.distance - b.distance);
156
+ return candidates[0]?.branch ?? null;
157
+ }
158
+ async function branchSummary(exec, branch, branches, cwd) {
159
+ const origin = `origin/${branch}`;
160
+ const [originRef, localRef] = await Promise.all([
161
+ cmd(exec, ["rev-parse", "--verify", "--quiet", origin], cwd),
162
+ cmd(exec, ["rev-parse", "--verify", "--quiet", branch], cwd),
163
+ ]);
164
+ const hasOrigin = originRef.code === 0;
165
+ const localExists = localRef.code === 0;
166
+ let ahead = null;
167
+ let behind = null;
168
+ if (hasOrigin) {
169
+ const [aheadRes, behindRes] = await Promise.all([
170
+ cmd(exec, ["rev-list", "--count", `${origin}..${branch}`], cwd),
171
+ cmd(exec, ["rev-list", "--count", `${branch}..${origin}`], cwd),
172
+ ]);
173
+ if (aheadRes.code === 0)
174
+ ahead = Number(aheadRes.stdout.trim()) || 0;
175
+ if (behindRes.code === 0)
176
+ behind = Number(behindRes.stdout.trim()) || 0;
177
+ }
178
+ const [ffFrom, mainSync] = await Promise.all([
179
+ fastForwardSource(exec, branch, branches, cwd),
180
+ branchVsMain(exec, branch, cwd),
181
+ ]);
182
+ return { branch, ahead, behind, hasOrigin, localExists, ffFrom, mainSync };
183
+ }
184
+ async function rowFreshness(exec, row, cwd) {
185
+ // The revision goes BEFORE `--`: `git log -1 <branch> -- <subdir>`. Appending
186
+ // the branch after `--` would read it as a path, silently degrading to HEAD.
187
+ const args = ["log", "-1", "--format=%cI%n%h", row.branch];
188
+ if (row.subdir)
189
+ args.push("--", row.subdir);
190
+ const [res, changesVsMain] = await Promise.all([
191
+ cmd(exec, args, cwd),
192
+ subdirVsMain(exec, row.branch, row.subdir, cwd),
193
+ ]);
194
+ if (res.code !== 0)
195
+ return { lastPushAt: null, lastPushSha: null, changesVsMain };
196
+ const [at, sha] = res.stdout.trim().split("\n");
197
+ return { lastPushAt: at?.trim() || null, lastPushSha: sha?.trim() || null, changesVsMain };
198
+ }
199
+ export async function getDeploymentsStatus(config, exec = run) {
200
+ const rows = configuredDeployments(config);
201
+ if (!rows.length) {
202
+ return {
203
+ enabled: false,
204
+ rows: [],
205
+ branches: [],
206
+ root: null,
207
+ dirty: false,
208
+ currentBranch: null,
209
+ };
210
+ }
211
+ const cwd = deployRoot(config);
212
+ const branches = deploymentBranches(rows);
213
+ const [dirtRes, currentRes, ...summaries] = await Promise.all([
214
+ cmd(exec, ["status", "--porcelain"], cwd),
215
+ cmd(exec, ["branch", "--show-current"], cwd),
216
+ ...branches.map((b) => branchSummary(exec, b, branches, cwd)),
217
+ ]);
218
+ // Freshness (+ subdir-scoped sync, #0367) is cached per (branch, subdir) —
219
+ // two rows sharing both run one set of git calls, not two.
220
+ const freshness = new Map();
221
+ const resolvedRows = await Promise.all(rows.map(async (row) => {
222
+ const key = `${row.branch}\u0000${row.subdir ?? ""}`;
223
+ let pending = freshness.get(key);
224
+ if (!pending) {
225
+ pending = rowFreshness(exec, row, cwd);
226
+ freshness.set(key, pending);
227
+ }
228
+ const f = await pending;
229
+ return {
230
+ name: row.name,
231
+ service: row.service ?? row.name,
232
+ branch: row.branch,
233
+ provider: row.provider ?? null,
234
+ url: row.url ?? null,
235
+ dashboardUrl: row.dashboardUrl ?? null,
236
+ subdir: row.subdir ?? null,
237
+ lastPushAt: f.lastPushAt,
238
+ lastPushSha: f.lastPushSha,
239
+ changesVsMain: f.changesVsMain,
240
+ };
241
+ }));
242
+ return {
243
+ enabled: true,
244
+ rows: resolvedRows,
245
+ branches: summaries,
246
+ root: cwd,
247
+ dirty: dirtRes.code === 0 ? dirtRes.stdout.trim() !== "" : true,
248
+ currentBranch: currentRes.code === 0 ? currentRes.stdout.trim() || null : null,
249
+ };
250
+ }
251
+ /**
252
+ * Deploy one branch: a plain `git push origin <branch>`, or — when the branch
253
+ * is strictly behind another configured branch (prod behind main) — a
254
+ * fast-forward of the local ref first, then the push. The fast-forward uses
255
+ * `git merge --ff-only <src>` when the checkout is ON that branch (git refuses
256
+ * to fetch into a checked-out branch) and `git fetch . <src>:<branch>` — which
257
+ * git itself refuses on non-fast-forward — otherwise. There is no code path
258
+ * that pushes with --force: every non-fast-forward case fails loudly with
259
+ * git's own refusal in the output.
260
+ */
261
+ export async function deployBranch(config, branch, exec = run) {
262
+ const rows = configuredDeployments(config);
263
+ if (!rows.length)
264
+ return { ok: false, output: "Deployments are not configured for this repository." };
265
+ if (!deploymentBranches(rows).includes(branch))
266
+ return { ok: false, output: `"${branch}" is not a configured deployment branch.` };
267
+ const cwd = deployRoot(config);
268
+ const dirty = await cmd(exec, ["status", "--porcelain"], cwd);
269
+ if (dirty.code !== 0)
270
+ return { ok: false, output: "Could not read the git status of the checkout." };
271
+ if (dirty.stdout.trim() !== "")
272
+ return {
273
+ ok: false,
274
+ output: "The checkout has uncommitted changes — commit or stash them before deploying. " +
275
+ "This is the same dirty-tree guard `just release` uses.",
276
+ };
277
+ const local = await cmd(exec, ["rev-parse", "--verify", "--quiet", branch], cwd);
278
+ if (local.code !== 0)
279
+ return {
280
+ ok: false,
281
+ output: `No local branch "${branch}" exists in this checkout — fetch or create it before deploying ` +
282
+ `(e.g. git fetch origin "${branch}:" then git checkout "${branch}").`,
283
+ };
284
+ const branches = deploymentBranches(rows);
285
+ const src = await fastForwardSource(exec, branch, branches, cwd);
286
+ if (src) {
287
+ // On the target branch, `fetch . src:branch` refuses ("refusing to fetch
288
+ // into branch … checked out"); merge --ff-only is the equivalent ref move
289
+ // there, and equally refuses a non-fast-forward.
290
+ const current = await cmd(exec, ["branch", "--show-current"], cwd);
291
+ const onBranch = current.code === 0 && current.stdout.trim() === branch;
292
+ const ff = onBranch
293
+ ? await cmd(exec, ["merge", "--ff-only", src], cwd)
294
+ : await cmd(exec, ["fetch", ".", `${src}:${branch}`], cwd);
295
+ if (ff.code !== 0) {
296
+ return {
297
+ ok: false,
298
+ output: `Could not fast-forward ${branch} to ${src} — the branches have diverged, ` +
299
+ `so the deploy was refused rather than force-pushed.\n` +
300
+ (captureOutput(ff.stdout, ff.stderr) || ff.error?.message || ""),
301
+ };
302
+ }
303
+ const pushed = await cmd(exec, ["push", "origin", branch], cwd, 120_000);
304
+ if (pushed.code !== 0) {
305
+ return {
306
+ ok: false,
307
+ output: `Fast-forwarded ${branch} to ${src}, but the push to origin failed — the remote may have moved. ` +
308
+ `Nothing was force-pushed; origin still has the old ${branch}. ` +
309
+ `The local ${branch} is now at ${src}, so the NEXT deploy will be a plain push.\n` +
310
+ (captureOutput(pushed.stdout, pushed.stderr) || pushed.error?.message || ""),
311
+ };
312
+ }
313
+ return { ok: true, output: `Fast-forwarded ${branch} to ${src} and pushed to origin.` };
314
+ }
315
+ const pushed = await cmd(exec, ["push", "origin", branch], cwd, 120_000);
316
+ if (pushed.code !== 0) {
317
+ return {
318
+ ok: false,
319
+ output: `Could not push ${branch} to origin — the remote may have commits this checkout hasn't fetched. ` +
320
+ `Nothing was force-pushed.\n` +
321
+ (captureOutput(pushed.stdout, pushed.stderr) || pushed.error?.message || ""),
322
+ };
323
+ }
324
+ return { ok: true, output: `Pushed ${branch} to origin.` };
325
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Durable task-diff snapshots.
3
+ *
4
+ * A task worktree and branch are intentionally removed after a successful
5
+ * close-out. Keep the reviewed diff in `.repoos/` first so the Changes tab
6
+ * remains useful for completed tasks without retaining Git resources forever.
7
+ */
8
+ import type { DiffResult, DiffStats } from "../core/git.js";
9
+ declare const SNAPSHOT_VERSION = 1;
10
+ export interface DiffSnapshot {
11
+ version: typeof SNAPSHOT_VERSION;
12
+ capturedAt: string;
13
+ stats: DiffStats;
14
+ diff: DiffResult;
15
+ }
16
+ /** Persist a complete task diff atomically. Best-effort: close-out must not fail solely because history cannot be cached. */
17
+ export declare function saveDiffSnapshot(root: string, cacheDir: string, taskId: string, stats: DiffStats, diff: DiffResult): void;
18
+ /** Load the captured completed-task diff, or null if this task predates snapshots. */
19
+ export declare function loadDiffSnapshot(root: string, cacheDir: string, taskId: string): DiffSnapshot | null;
20
+ export {};
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Durable task-diff snapshots.
3
+ *
4
+ * A task worktree and branch are intentionally removed after a successful
5
+ * close-out. Keep the reviewed diff in `.repoos/` first so the Changes tab
6
+ * remains useful for completed tasks without retaining Git resources forever.
7
+ */
8
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
9
+ import { join } from "node:path";
10
+ const SNAPSHOT_VERSION = 1;
11
+ const SNAPSHOT_DIR = "diffs";
12
+ function snapshotPath(root, cacheDir, taskId) {
13
+ // Task IDs are normally numeric, but never let an unexpected ID influence a
14
+ // filesystem path outside RepoOS's cache directory.
15
+ if (!/^[A-Za-z0-9_-]+$/.test(taskId))
16
+ return null;
17
+ return join(root, cacheDir, SNAPSHOT_DIR, `${taskId}.json`);
18
+ }
19
+ /** Persist a complete task diff atomically. Best-effort: close-out must not fail solely because history cannot be cached. */
20
+ export function saveDiffSnapshot(root, cacheDir, taskId, stats, diff) {
21
+ const file = snapshotPath(root, cacheDir, taskId);
22
+ if (!file)
23
+ return;
24
+ let temp = null;
25
+ try {
26
+ mkdirSync(join(root, cacheDir, SNAPSHOT_DIR), { recursive: true });
27
+ temp = `${file}.${process.pid}.tmp`;
28
+ const snapshot = {
29
+ version: SNAPSHOT_VERSION,
30
+ capturedAt: new Date().toISOString(),
31
+ stats,
32
+ diff,
33
+ };
34
+ writeFileSync(temp, JSON.stringify(snapshot), "utf8");
35
+ renameSync(temp, file);
36
+ }
37
+ catch {
38
+ /* History is a convenience; never block a successfully validated release. */
39
+ }
40
+ finally {
41
+ if (temp && existsSync(temp)) {
42
+ try {
43
+ unlinkSync(temp);
44
+ }
45
+ catch {
46
+ /* best-effort */
47
+ }
48
+ }
49
+ }
50
+ }
51
+ /** Load the captured completed-task diff, or null if this task predates snapshots. */
52
+ export function loadDiffSnapshot(root, cacheDir, taskId) {
53
+ const file = snapshotPath(root, cacheDir, taskId);
54
+ if (!file || !existsSync(file))
55
+ return null;
56
+ try {
57
+ const parsed = JSON.parse(readFileSync(file, "utf8"));
58
+ if (parsed.version !== SNAPSHOT_VERSION ||
59
+ typeof parsed.capturedAt !== "string" ||
60
+ !parsed.stats ||
61
+ !parsed.diff ||
62
+ typeof parsed.stats.filesChanged !== "number" ||
63
+ typeof parsed.stats.additions !== "number" ||
64
+ typeof parsed.stats.deletions !== "number" ||
65
+ typeof parsed.diff.patch !== "string" ||
66
+ typeof parsed.diff.truncated !== "boolean")
67
+ return null;
68
+ return parsed;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }