@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,778 @@
1
+ /**
2
+ * Task context pack generation.
3
+ *
4
+ * Deterministically builds a concise, bounded, human-inspectable summary of
5
+ * everything an agent needs to know before its first tool call: the task spec,
6
+ * applicable constraints, worktree state, likely implementation files, relevant
7
+ * tests, verification commands, and bootstrap telemetry. The pack is
8
+ * driver-neutral (plain markdown), path-guarded, and cached against
9
+ * authoritative repository state so repeated turns on the same task skip the
10
+ * generation cost.
11
+ *
12
+ * Zero runtime deps — `node:fs`, `node:path`, `node:crypto` only. File
13
+ * relevance uses deterministic rules (area mapping, symbol references, import
14
+ * graph, test proximity) rather than an extra LLM call.
15
+ */
16
+ import { createHash } from "node:crypto";
17
+ import { spawnSync } from "node:child_process";
18
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
19
+ import { join, relative, extname } from "node:path";
20
+ /** Maximum byte size of a context pack before relevance-ranked truncation. */
21
+ const PACK_BYTE_BUDGET = 24 * 1024;
22
+ /** File extensions we consider source code for relevance ranking. */
23
+ const SOURCE_EXTS = new Set([
24
+ ".ts",
25
+ ".tsx",
26
+ ".js",
27
+ ".jsx",
28
+ ".vue",
29
+ ".svelte",
30
+ ".css",
31
+ ".scss",
32
+ ".less",
33
+ ".rs",
34
+ ".go",
35
+ ".py",
36
+ ".rb",
37
+ ".json",
38
+ ".toml",
39
+ ".yaml",
40
+ ".yml",
41
+ ".md",
42
+ ".mdx",
43
+ ]);
44
+ /** File extensions that are tests. */
45
+ const TEST_EXTS = new Set([
46
+ ".test.ts",
47
+ ".test.tsx",
48
+ ".spec.ts",
49
+ ".spec.tsx",
50
+ ".test.js",
51
+ ".test.jsx",
52
+ ".spec.js",
53
+ ".spec.jsx",
54
+ ".test.py",
55
+ ".test.rs",
56
+ ".test.go",
57
+ ]);
58
+ /** Directories we skip altogether when scanning source files. */
59
+ const SKIP_DIRS = new Set([
60
+ "node_modules",
61
+ ".git",
62
+ ".repoos",
63
+ "dist",
64
+ ".next",
65
+ ".nuxt",
66
+ "build",
67
+ "coverage",
68
+ "__pycache__",
69
+ ".venv",
70
+ "venv",
71
+ ]);
72
+ // ---- Repo map (stable across tasks) ----
73
+ function cacheDir(root, cacheDirName) {
74
+ return join(root, cacheDirName);
75
+ }
76
+ function repoMapPath(config) {
77
+ return join(config.root, config.cacheDir, "repo-map.json");
78
+ }
79
+ /**
80
+ * Best-effort HEAD hash. Returns "unknown" when git is missing or no commits
81
+ * exist, so the cache still functions but invalidates on every run.
82
+ */
83
+ function headHash(root) {
84
+ try {
85
+ const run = spawnSync("git", ["rev-parse", "HEAD"], {
86
+ cwd: root,
87
+ encoding: "utf8",
88
+ timeout: 4000,
89
+ });
90
+ return run.status === 0 ? run.stdout.trim() : "unknown";
91
+ }
92
+ catch {
93
+ return "unknown";
94
+ }
95
+ }
96
+ function isTestFile(name) {
97
+ for (const ext of TEST_EXTS) {
98
+ if (name.endsWith(ext))
99
+ return true;
100
+ }
101
+ // Also match `tests/` directory convention
102
+ return false;
103
+ }
104
+ function isSourceFile(name) {
105
+ const ext = extname(name).toLowerCase();
106
+ return (SOURCE_EXTS.has(ext) ||
107
+ // Also include files in test directories with test patterns
108
+ isTestFile(name));
109
+ }
110
+ /**
111
+ * Extract import paths from source content using a simple regex. Handles:
112
+ * import ... from "./foo"
113
+ * import ... from "../bar"
114
+ * import "./side-effect"
115
+ * require("./x")
116
+ * Not exhaustive, but fast and works for the vast majority of TS/JS.
117
+ */
118
+ function extractImports(content) {
119
+ const out = [];
120
+ const re = /(?:import\s+(?:[\s\S]*?\s+from\s+)?|require\s*\()["']([^"']+)["']/g;
121
+ let m;
122
+ while ((m = re.exec(content)) !== null) {
123
+ const spec = m[1];
124
+ // Only keep local imports (relative paths), not package imports.
125
+ if (spec.startsWith("."))
126
+ out.push(spec);
127
+ }
128
+ return out;
129
+ }
130
+ /** Walk a directory tree for source files and return map entries. */
131
+ function walkSourceFiles(dir, root, skip, acc) {
132
+ if (!existsSync(dir))
133
+ return;
134
+ for (const entry of readdirSync(dir)) {
135
+ if (entry.startsWith(".") || skip.has(entry))
136
+ continue;
137
+ const full = join(dir, entry);
138
+ let st;
139
+ try {
140
+ st = statSync(full);
141
+ }
142
+ catch {
143
+ continue;
144
+ }
145
+ if (st.isDirectory()) {
146
+ walkSourceFiles(full, root, skip, acc);
147
+ }
148
+ else if (st.isFile() && isSourceFile(entry)) {
149
+ let content = "";
150
+ let imports = [];
151
+ try {
152
+ content = readFileSync(full, "utf8");
153
+ imports = extractImports(content);
154
+ }
155
+ catch {
156
+ /* unreadable — skip */
157
+ }
158
+ acc.push({
159
+ path: relative(root, full).split("\\").join("/"),
160
+ size: st.size,
161
+ imports,
162
+ mtimeMs: st.mtimeMs,
163
+ });
164
+ }
165
+ }
166
+ }
167
+ /**
168
+ * Build or load the cached repository file map. The map is stable across
169
+ * tasks: it changes only when HEAD moves or the source tree changes. A cache
170
+ * miss walks the source directories and caches the result keyed by HEAD hash.
171
+ */
172
+ export function buildRepoMap(config) {
173
+ const path = repoMapPath(config);
174
+ const hash = headHash(config.root);
175
+ if (existsSync(path)) {
176
+ try {
177
+ const cached = JSON.parse(readFileSync(path, "utf8"));
178
+ if (cached.headHash === hash)
179
+ return { map: cached, cacheHit: true };
180
+ }
181
+ catch {
182
+ /* corrupt cache — rebuild */
183
+ }
184
+ }
185
+ const files = [];
186
+ const roots = ["src"];
187
+ for (const r of roots) {
188
+ walkSourceFiles(join(config.root, r), config.root, SKIP_DIRS, files);
189
+ }
190
+ const map = {
191
+ headHash: hash,
192
+ generatedAt: new Date().toISOString(),
193
+ files,
194
+ roots,
195
+ };
196
+ const dir = cacheDir(config.root, config.cacheDir);
197
+ if (!existsSync(dir))
198
+ mkdirSync(dir, { recursive: true });
199
+ try {
200
+ writeFileSync(path, JSON.stringify(map));
201
+ }
202
+ catch {
203
+ /* best-effort — cache write failure is not fatal */
204
+ }
205
+ return { map, cacheHit: false };
206
+ }
207
+ // ---- Cache-key building ----
208
+ function contentHash(content) {
209
+ return createHash("sha256").update(content).digest("hex").slice(0, 16);
210
+ }
211
+ /**
212
+ * Read AGENTS.md content (or CLAUDE.md as fallback). Returns empty string
213
+ * when neither exists.
214
+ */
215
+ function readAgentsContent(root) {
216
+ for (const name of ["AGENTS.md", "CLAUDE.md"]) {
217
+ const p = join(root, name);
218
+ if (existsSync(p)) {
219
+ try {
220
+ return readFileSync(p, "utf8");
221
+ }
222
+ catch {
223
+ /* unreadable */
224
+ }
225
+ }
226
+ }
227
+ return "";
228
+ }
229
+ /**
230
+ * Concatenate relevant docs (docs/ dir markdown files) for cache invalidation.
231
+ * Only includes the first 64KB to keep hashing fast.
232
+ */
233
+ function readDocsContent(root, docsDir) {
234
+ const docsPath = join(root, docsDir);
235
+ if (!existsSync(docsPath))
236
+ return "";
237
+ let out = "";
238
+ const walk = (dir) => {
239
+ if (out.length > 64 * 1024)
240
+ return;
241
+ try {
242
+ for (const e of readdirSync(dir)) {
243
+ if (e.startsWith("."))
244
+ continue;
245
+ const full = join(dir, e);
246
+ const st = statSync(full);
247
+ if (st.isDirectory())
248
+ walk(full);
249
+ else if (extname(e) === ".md") {
250
+ try {
251
+ out += readFileSync(full, "utf8");
252
+ }
253
+ catch {
254
+ /* skip */
255
+ }
256
+ }
257
+ }
258
+ }
259
+ catch {
260
+ /* skip */
261
+ }
262
+ };
263
+ walk(docsPath);
264
+ return out.slice(0, 64 * 1024);
265
+ }
266
+ /** Hash of dependency manifests for cache invalidation. */
267
+ function depManifestHash(root) {
268
+ const manifests = ["package.json", "package-lock.json", "bun.lock", "bun.lockb"];
269
+ let combined = "";
270
+ for (const m of manifests) {
271
+ const p = join(root, m);
272
+ if (existsSync(p)) {
273
+ try {
274
+ combined += readFileSync(p, "utf8");
275
+ }
276
+ catch {
277
+ /* skip */
278
+ }
279
+ }
280
+ }
281
+ return combined ? contentHash(combined) : "no-manifests";
282
+ }
283
+ /** Build cache inputs from the current state. */
284
+ function buildCacheInputs(config, task, head, worktreeDirty, worktreeUntracked, worktreeDiffSummary) {
285
+ return {
286
+ headHash: head,
287
+ taskContent: task.body,
288
+ agentsContent: readAgentsContent(config.root),
289
+ docsContent: readDocsContent(config.root, config.docsDir),
290
+ depHash: depManifestHash(config.root),
291
+ worktreeDirty,
292
+ worktreeUntracked,
293
+ worktreeDiffSummary,
294
+ };
295
+ }
296
+ function inputsHash(inputs) {
297
+ const serialized = [
298
+ inputs.headHash,
299
+ contentHash(inputs.taskContent),
300
+ contentHash(inputs.agentsContent),
301
+ contentHash(inputs.docsContent),
302
+ inputs.depHash,
303
+ String(inputs.worktreeDirty),
304
+ inputs.worktreeUntracked.join(","),
305
+ contentHash(inputs.worktreeDiffSummary),
306
+ ].join("|");
307
+ return contentHash(serialized);
308
+ }
309
+ function contextCachePath(config, taskId) {
310
+ return join(config.root, config.cacheDir, `context-${taskId}.json`);
311
+ }
312
+ // ---- Worktree state helpers ----
313
+ /**
314
+ * Get worktree dirt summary: dirty/clean, untracked files (capped), and a
315
+ * summary of the first 15 changed lines.
316
+ */
317
+ function worktreeState(config, _branch, cwd) {
318
+ let dirty = false;
319
+ let untracked = [];
320
+ let diffSummary = "";
321
+ try {
322
+ const status = spawnSync("git", ["status", "--porcelain"], {
323
+ cwd,
324
+ encoding: "utf8",
325
+ timeout: 4000,
326
+ });
327
+ if (status.status === 0 && status.stdout.trim()) {
328
+ dirty = true;
329
+ const lines = status.stdout.trim().split("\n");
330
+ const untrackedLines = lines.filter((l) => l.startsWith("??"));
331
+ untracked = untrackedLines.slice(0, 20).map((l) => l.slice(3).trim());
332
+ }
333
+ }
334
+ catch {
335
+ /* best-effort */
336
+ }
337
+ try {
338
+ if (dirty) {
339
+ // Get a compact diff summary: first 15 changed files with +/- counts
340
+ const diff = spawnSync("git", ["diff", "--stat"], { cwd, encoding: "utf8", timeout: 4000 });
341
+ if (diff.status === 0 && diff.stdout.trim()) {
342
+ const lines = diff.stdout.trim().split("\n");
343
+ // The last line is the summary (e.g. "3 files changed, 12 insertions(+), 5 deletions(-)")
344
+ // The preceding lines are per-file stats
345
+ const fileLines = lines.slice(0, -1).slice(0, 25);
346
+ diffSummary = fileLines.join("\n");
347
+ const summaryLine = lines[lines.length - 1] ?? "";
348
+ if (diffSummary)
349
+ diffSummary += "\n" + summaryLine;
350
+ else
351
+ diffSummary = summaryLine;
352
+ }
353
+ }
354
+ }
355
+ catch {
356
+ /* best-effort */
357
+ }
358
+ return { dirty, untracked, diffSummary };
359
+ }
360
+ // ---- File relevance ranking ----
361
+ /**
362
+ * Map a task area to likely source directories. Extended as conventions grow;
363
+ * currently covers the self-hosted RepoOS layout.
364
+ */
365
+ function areaToDirs(area) {
366
+ const map = {
367
+ agent: ["src/server/agents.ts", "src/server/server.ts", "src/core/git.ts"],
368
+ server: ["src/server/"],
369
+ core: ["src/core/"],
370
+ cli: ["src/cli/", "src/commands/"],
371
+ ui: ["src/ui-app/"],
372
+ build: ["src/core/build.ts", "scripts/", "tsconfig.json"],
373
+ config: ["src/core/config.ts", "repoos.toml"],
374
+ git: ["src/core/git.ts"],
375
+ tasks: [
376
+ "src/core/task.ts",
377
+ "src/server/write.ts",
378
+ "src/core/indexer.ts",
379
+ "src/core/frontmatter.ts",
380
+ ],
381
+ checks: ["src/commands/check.ts"],
382
+ tests: ["src/ui-app/tests/"],
383
+ docs: ["docs/"],
384
+ review: ["src/server/done.ts", "src/server/write.ts"],
385
+ };
386
+ return map[area] ?? map[area.toLowerCase()] ?? [];
387
+ }
388
+ /**
389
+ * Scan task body for file path references (e.g. "src/server/agents.ts").
390
+ * Matches repo-relative paths that look like source files.
391
+ */
392
+ function extractFileReferences(body) {
393
+ const out = [];
394
+ const re = /(`|["'\s])(src\/[\w\/.-]+\.(?:ts|tsx|js|vue|css|json|md|toml))/g;
395
+ let m;
396
+ while ((m = re.exec(body)) !== null) {
397
+ out.push(m[2]);
398
+ }
399
+ return [...new Set(out)];
400
+ }
401
+ /**
402
+ * Rank files by relevance to a task using deterministic signals:
403
+ * 1. Area → directory mapping (strong signal)
404
+ * 2. File references in task body (strong signal)
405
+ * 3. Import proximity (files that import or are imported by signaled files)
406
+ * 4. Recent modification (files changed in the same areas)
407
+ *
408
+ * Each file gets a relevance rank (higher = more relevant). The pack includes
409
+ * files sorted by rank, capped by the byte budget.
410
+ */
411
+ function rankFiles(config, task, repoMap) {
412
+ const scores = new Map();
413
+ const add = (path, score, reason) => {
414
+ if (!scores.has(path)) {
415
+ scores.set(path, { score: 0, reasons: [] });
416
+ }
417
+ const entry = scores.get(path);
418
+ entry.score += score;
419
+ if (!entry.reasons.includes(reason))
420
+ entry.reasons.push(reason);
421
+ };
422
+ // 1. Area-based: files in mapped directories
423
+ const areaDirs = areaToDirs(task.area);
424
+ for (const ad of areaDirs) {
425
+ for (const f of repoMap.files) {
426
+ if (f.path === ad || f.path.startsWith(ad)) {
427
+ add(f.path, 10, `area match: "${task.area}"`);
428
+ }
429
+ }
430
+ }
431
+ // 2. File references in task body
432
+ const refs = extractFileReferences(task.body);
433
+ for (const ref of refs) {
434
+ const exact = repoMap.files.find((f) => f.path === ref);
435
+ if (exact) {
436
+ add(exact.path, 20, "task body reference");
437
+ }
438
+ // Partial match: file name fragment
439
+ for (const f of repoMap.files) {
440
+ if (f.path.includes(ref.replace(/^src\//, ""))) {
441
+ add(f.path, 5, `partial body reference: ${ref}`);
442
+ }
443
+ }
444
+ }
445
+ // 3. Import proximity: files connected to already-scored files
446
+ const scoredPaths = new Set(scores.keys());
447
+ let pendingPaths = new Set(scoredPaths);
448
+ for (let hop = 0; hop < 2; hop++) {
449
+ const next = new Set();
450
+ for (const sp of pendingPaths) {
451
+ const entry = repoMap.files.find((f) => f.path === sp);
452
+ if (!entry)
453
+ continue;
454
+ for (const imp of entry.imports) {
455
+ // Resolve relative import to an absolute repo path (best-effort)
456
+ for (const f of repoMap.files) {
457
+ if (f.path.endsWith(imp.replace(/^\.\//, "").replace(/\.\.\//g, ""))) {
458
+ if (!scoredPaths.has(f.path)) {
459
+ next.add(f.path);
460
+ add(f.path, 4 - hop, `imported by ${sp}`);
461
+ }
462
+ }
463
+ }
464
+ }
465
+ }
466
+ pendingPaths = next;
467
+ }
468
+ // 4. Recent modifications: files with newer mtimes in scored directories
469
+ const now = Date.now();
470
+ const recentThreshold = now - 7 * 24 * 60 * 60 * 1000; // 7 days
471
+ for (const f of repoMap.files) {
472
+ if (f.mtimeMs >= recentThreshold) {
473
+ add(f.path, 2, "recently modified (≤7 days)");
474
+ }
475
+ }
476
+ // 5. Test files near relevant areas
477
+ for (const f of repoMap.files) {
478
+ if (isTestFile(f.path)) {
479
+ // Check if the test path corresponds to a scored source file
480
+ const sourcePath = f.path
481
+ .replace(/\/tests\//, "/src/")
482
+ .replace(/\.test\./, ".")
483
+ .replace(/\.spec\./, ".");
484
+ for (const sp of scoredPaths) {
485
+ if (sp.includes(sourcePath.replace(/^src\//, "")) ||
486
+ sourcePath.includes(sp.replace(/^src\//, ""))) {
487
+ add(f.path, 3, `test for relevant area`);
488
+ break;
489
+ }
490
+ }
491
+ }
492
+ }
493
+ // Convert to sorted array
494
+ const result = [];
495
+ for (const [path, { score, reasons }] of scores) {
496
+ if (SKIP_DIRS.has(path.split("/")[0] ?? ""))
497
+ continue;
498
+ result.push({
499
+ path,
500
+ reason: reasons.slice(0, 3).join("; "),
501
+ rank: score,
502
+ isTest: isTestFile(path),
503
+ });
504
+ }
505
+ result.sort((a, b) => b.rank - a.rank);
506
+ return result;
507
+ }
508
+ // ---- Context pack generation ----
509
+ /**
510
+ * Render a bounded context pack as markdown. Files are included up to the
511
+ * byte budget, with relevance-ranked truncation.
512
+ */
513
+ function renderPack(config, task, branch, cwd, cacheHit, bootstrapResult, relevantFiles, worktreeInfo) {
514
+ const lines = [];
515
+ const push = (s) => lines.push(s);
516
+ push("## Task Context Pack");
517
+ push("");
518
+ push(`**Task:** #${task.id} — ${task.title}`);
519
+ push(`**Area:** ${task.area || "unset"}`);
520
+ push(`**Type:** ${task.type}`);
521
+ push(`**Priority:** ${task.priority}`);
522
+ push(`**Cache:** ${cacheHit ? "hit" : "miss"}`);
523
+ push("");
524
+ push("### Task Specification");
525
+ push("");
526
+ // Include the task body (up to 3KB to leave budget for other sections)
527
+ const bodyMax = 3 * 1024;
528
+ const body = task.body.length > bodyMax ? task.body.slice(0, bodyMax) + "\n\n... (truncated)" : task.body;
529
+ push(body || "(no task body)");
530
+ push("");
531
+ // ---- Worktree State ----
532
+ push("### Worktree State");
533
+ push("");
534
+ push(`**Root:** ${config.root}`);
535
+ push(`**Branch:** ${branch}`);
536
+ push(`**Worktree:** ${cwd}`);
537
+ push(`**Dirty:** ${worktreeInfo.dirty ? "YES — uncommitted changes or untracked files" : "clean"}`);
538
+ if (worktreeInfo.untracked.length > 0) {
539
+ push("**Untracked files:**");
540
+ for (const u of worktreeInfo.untracked.slice(0, 10)) {
541
+ push(` - ${u}`);
542
+ }
543
+ if (worktreeInfo.untracked.length > 10) {
544
+ push(` ... and ${worktreeInfo.untracked.length - 10} more`);
545
+ }
546
+ }
547
+ if (worktreeInfo.diffSummary) {
548
+ push("");
549
+ push("**Dirty diff summary:**");
550
+ push("```");
551
+ push(worktreeInfo.diffSummary);
552
+ push("```");
553
+ }
554
+ push("");
555
+ // ---- AGENTS Constraints ----
556
+ const agentsContent = readAgentsContent(config.root);
557
+ if (agentsContent) {
558
+ push("### Applicable Constraints (AGENTS.md)");
559
+ push("");
560
+ // Include the first 2KB of AGENTS.md — enough for the operating loop
561
+ // and rules without ballooning the pack.
562
+ const agentsMax = 2 * 1024;
563
+ const agents = agentsContent.length > agentsMax
564
+ ? agentsContent.slice(0, agentsMax) +
565
+ "\n\n... (AGENTS.md truncated — read the full file when needed)"
566
+ : agentsContent;
567
+ push(agents);
568
+ push("");
569
+ }
570
+ // ---- Likely Implementation Files ----
571
+ push("### Likely Implementation Files");
572
+ push("");
573
+ let fileBudget = PACK_BYTE_BUDGET;
574
+ // Estimate current size
575
+ let currentSize = lines.join("\n").length;
576
+ fileBudget = Math.max(fileBudget - currentSize, 4 * 1024);
577
+ let fileBytes = 0;
578
+ const maxFiles = 20;
579
+ const included = [];
580
+ for (const f of relevantFiles) {
581
+ if (included.length >= maxFiles)
582
+ break;
583
+ const line = `- \`${f.path}\``;
584
+ const reasonLine = ` ${f.isTest ? "[TEST] " : ""}${f.reason} (rank=${f.rank})`;
585
+ const entryBytes = line.length + reasonLine.length + 2;
586
+ if (fileBytes + entryBytes > fileBudget)
587
+ break;
588
+ included.push(f);
589
+ fileBytes += entryBytes;
590
+ }
591
+ // Group by source vs test
592
+ const sources = included.filter((f) => !f.isTest);
593
+ const tests = included.filter((f) => f.isTest);
594
+ if (sources.length > 0) {
595
+ push("**Source files:**");
596
+ for (const f of sources) {
597
+ push(`- \`${f.path}\` \n ${f.reason} (rank=${f.rank})`);
598
+ }
599
+ push("");
600
+ }
601
+ if (tests.length > 0) {
602
+ push("**Test files:**");
603
+ for (const f of tests) {
604
+ push(`- \`${f.path}\` \n [TEST] ${f.reason} (rank=${f.rank})`);
605
+ }
606
+ push("");
607
+ }
608
+ if (sources.length === 0 && tests.length === 0) {
609
+ push("_(no high-relevance files identified — scan the source tree)_");
610
+ push("");
611
+ }
612
+ // ---- Verification Commands ----
613
+ push("### Verification Commands");
614
+ push("");
615
+ push("```bash");
616
+ push("repoos check # full check: build, typecheck, tests, UI smoke test");
617
+ push("bun run build # compile (`npm run build` only if the repo doesn't use Bun)");
618
+ push("bun run test # test suite (`npm test` only if the repo doesn't use Bun)");
619
+ push("bun run build:ui # UI-only build");
620
+ push("```");
621
+ push("");
622
+ // ---- Managed Preview ----
623
+ push("### Managed Preview");
624
+ push("");
625
+ push("RepoOS serves a read-only preview of the worktree — you never need localhost or a port:");
626
+ push("- Preview requests are the human's to make — the human requests one manually from the UI when they want to see a change. Do NOT auto-request one before handoff.");
627
+ push("- Request (only if the human explicitly asks you to verify a change the way a browser would see it): emit the exact signal line `::repoos-preview-request::` in your response");
628
+ push("- RepoOS validates your live run, starts the preview from your worktree, probes it server-side, and records the preview URL + result in your transcript");
629
+ push("- View: the recorded preview URL (or the UI's Preview button)");
630
+ push("- Stop: `POST /api/tasks/:id/preview/stop` or close via UI");
631
+ push("- Previews are ephemeral: they stop when the task leaves active/review");
632
+ push("");
633
+ // ---- Bootstrap Telemetry ----
634
+ if (bootstrapResult) {
635
+ push("### Bootstrap Telemetry");
636
+ push("");
637
+ push(`**Outcome:** ${bootstrapResult.ok ? "PASSED" : "FAILED"}`);
638
+ push(`**Duration:** ${bootstrapResult.durationMs}ms`);
639
+ if (!bootstrapResult.ok && bootstrapResult.reason) {
640
+ push(`**Failure:** ${bootstrapResult.reason}`);
641
+ }
642
+ push("**Steps:**");
643
+ for (const step of bootstrapResult.steps) {
644
+ const icon = step.ok ? "✓" : "✗";
645
+ push(` ${icon} ${step.name} (${step.durationMs}ms)${step.detail ? ` — ${step.detail}` : ""}`);
646
+ }
647
+ push("");
648
+ }
649
+ // ---- Git Workflow ----
650
+ push("### Git Workflow");
651
+ push("");
652
+ push(`- Work on branch \`${branch}\` in \`${cwd}\``);
653
+ push(`- The main checkout is at \`${config.root}\``);
654
+ push("- Commit to the branch; never force-push");
655
+ return lines.join("\n");
656
+ }
657
+ /**
658
+ * Generate a task context pack. Uses a two-layer cache:
659
+ * 1. Repo map (file structure + imports) — stable across tasks, keyed by HEAD
660
+ * 2. Context pack — task-specific, keyed by all inputs that affect it
661
+ *
662
+ * Returns the pack with metadata including cache hit/miss and timing.
663
+ */
664
+ export function generateContextPack(config, task, branch, cwd, bootstrapResult) {
665
+ const start = Date.now();
666
+ const head = headHash(config.root);
667
+ // Worktree state
668
+ const wtState = worktreeState(config, branch, cwd);
669
+ // Build cache inputs
670
+ const inputs = buildCacheInputs(config, task, head, wtState.dirty, wtState.untracked, wtState.diffSummary);
671
+ const key = inputsHash(inputs);
672
+ // Check task-specific cache
673
+ const cachePath = contextCachePath(config, task.id);
674
+ if (existsSync(cachePath)) {
675
+ try {
676
+ const cached = JSON.parse(readFileSync(cachePath, "utf8"));
677
+ if (cached.cacheKey === key) {
678
+ return {
679
+ taskId: task.id,
680
+ generatedAt: cached.generatedAt,
681
+ cacheKey: key,
682
+ cacheHit: true,
683
+ generationMs: Date.now() - start,
684
+ content: cached.content,
685
+ size: cached.size,
686
+ bootstrap: bootstrapResult
687
+ ? {
688
+ ok: bootstrapResult.ok,
689
+ durationMs: bootstrapResult.durationMs,
690
+ steps: bootstrapResult.steps.map((s) => ({
691
+ name: s.name,
692
+ ok: s.ok,
693
+ durationMs: s.durationMs,
694
+ })),
695
+ }
696
+ : undefined,
697
+ };
698
+ }
699
+ }
700
+ catch {
701
+ /* corrupt — rebuild */
702
+ }
703
+ }
704
+ // Build repo map (its own cache layer)
705
+ const { map: repoMap } = buildRepoMap(config);
706
+ // Rank relevant files
707
+ const relevantFiles = rankFiles(config, task, repoMap);
708
+ // Render the pack
709
+ const content = renderPack(config, task, branch, cwd, false, bootstrapResult, relevantFiles, wtState);
710
+ const size = content.length;
711
+ // Persist in task cache
712
+ const cached = {
713
+ cacheKey: key,
714
+ generatedAt: new Date().toISOString(),
715
+ content,
716
+ size,
717
+ generationMs: Date.now() - start,
718
+ };
719
+ const dir = cacheDir(config.root, config.cacheDir);
720
+ if (!existsSync(dir))
721
+ mkdirSync(dir, { recursive: true });
722
+ try {
723
+ writeFileSync(cachePath, JSON.stringify(cached));
724
+ }
725
+ catch {
726
+ /* best-effort */
727
+ }
728
+ return {
729
+ taskId: task.id,
730
+ generatedAt: cached.generatedAt,
731
+ cacheKey: key,
732
+ cacheHit: false,
733
+ generationMs: cached.generationMs,
734
+ content,
735
+ size,
736
+ bootstrap: bootstrapResult
737
+ ? {
738
+ ok: bootstrapResult.ok,
739
+ durationMs: bootstrapResult.durationMs,
740
+ steps: bootstrapResult.steps.map((s) => ({
741
+ name: s.name,
742
+ ok: s.ok,
743
+ durationMs: s.durationMs,
744
+ })),
745
+ }
746
+ : undefined,
747
+ };
748
+ }
749
+ /**
750
+ * Build a compact resume preamble for a dirty worktree — surfaces existing
751
+ * partial changes so a resumed agent doesn't rediscover them from scratch.
752
+ */
753
+ export function resumePreamble(config, _task, branch, cwd) {
754
+ const wtState = worktreeState(config, branch, cwd);
755
+ if (!wtState.dirty)
756
+ return "";
757
+ const lines = [];
758
+ lines.push("## Resume State");
759
+ lines.push("");
760
+ lines.push("The worktree has existing changes from a previous turn:");
761
+ lines.push("");
762
+ if (wtState.untracked.length > 0) {
763
+ lines.push("**Untracked files (not yet committed):**");
764
+ for (const u of wtState.untracked.slice(0, 15)) {
765
+ lines.push(` - ${u}`);
766
+ }
767
+ lines.push("");
768
+ }
769
+ if (wtState.diffSummary) {
770
+ lines.push("**Changes from prior turn:**");
771
+ lines.push("```");
772
+ lines.push(wtState.diffSummary);
773
+ lines.push("```");
774
+ lines.push("");
775
+ }
776
+ lines.push("Review these changes before editing — you are continuing prior work.");
777
+ return lines.join("\n");
778
+ }