@repo-os/repoos 0.5.49 → 0.5.50

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 (189) hide show
  1. package/dist/.build-info.json +2 -2
  2. package/dist/.build-stamp.json +1 -1
  3. package/dist/cli/index.js +1 -1
  4. package/dist/commands/serve.d.ts +11 -0
  5. package/dist/commands/serve.js +33 -0
  6. package/dist/commands/ui-harness.js +11 -1
  7. package/dist/core/config.d.ts +32 -1
  8. package/dist/core/config.js +84 -1
  9. package/dist/core/repoos.d.ts +13 -1
  10. package/dist/core/repoos.js +5 -5
  11. package/dist/core/types.d.ts +8 -0
  12. package/dist/server/integration-orchestrator.d.ts +11 -0
  13. package/dist/server/integration-orchestrator.js +87 -1
  14. package/dist/server/preview.d.ts +9 -0
  15. package/dist/server/preview.js +12 -1
  16. package/dist/server/routes/support.d.ts +12 -0
  17. package/dist/server/routes/support.js +160 -4
  18. package/dist/server/routes/tasks.js +35 -18
  19. package/dist/server/server.d.ts +20 -0
  20. package/dist/server/server.js +29 -5
  21. package/dist/ui/assets/{AgentsView-B-w3_cUA.js → AgentsView-kzYSn-dX.js} +1 -1
  22. package/dist/ui/assets/ChecksView-BYIszmxn.js +1 -0
  23. package/dist/ui/assets/ChecksView-D79umAfM.css +1 -0
  24. package/dist/ui/assets/ContextView-CDHjupZ9.js +4 -0
  25. package/dist/ui/assets/{DashboardView-C7HwIylJ.js → DashboardView-CDIxxMbH.js} +1 -1
  26. package/dist/ui/assets/DeploymentsView-DI5Y69BM.css +1 -0
  27. package/dist/ui/assets/DeploymentsView-jcE87eqc.js +1 -0
  28. package/dist/ui/assets/DiffView-BpW0Agf3.css +1 -0
  29. package/dist/ui/assets/DiffView-C3HYdj7S.js +4 -0
  30. package/dist/ui/assets/{InputsView-D4XmIvgc.js → InputsView-B_NUIuXr.js} +1 -1
  31. package/dist/ui/assets/{LoginView-Bgv90FPK.js → LoginView-BjD2carP.js} +1 -1
  32. package/dist/ui/assets/ReleasesView-C-2JFAqC.js +3 -0
  33. package/dist/ui/assets/ReleasesView-DMhF7OTi.css +1 -0
  34. package/dist/ui/assets/SettingsView-CaloQYvQ.js +4 -0
  35. package/dist/ui/assets/WorkView-BGW29rZ6.css +1 -0
  36. package/dist/ui/assets/{WorkView-C3h32p3k.js → WorkView-CbqXqHFs.js} +2 -2
  37. package/dist/ui/assets/abnfDiagram-VCTEODGH-BFGqju3J.js +1 -0
  38. package/dist/ui/assets/{arc-BHZnmhhM.js → arc-DMqT1Ve5.js} +1 -1
  39. package/dist/ui/assets/architecture-7GRP2DOG-B4C2xWE4.js +1 -0
  40. package/dist/ui/assets/architectureDiagram-5GKGNRK7-CZhiMeBk.js +36 -0
  41. package/dist/ui/assets/{blockDiagram-I7D4REHJ-BsnD-5PV.js → blockDiagram-I7D4REHJ-B911Uy94.js} +6 -6
  42. package/dist/ui/assets/{c4Diagram-7LVT6UL2-CqpUjbtK.js → c4Diagram-7LVT6UL2-CaAFewRn.js} +7 -7
  43. package/dist/ui/assets/channel-DJ4Og_iH.js +1 -0
  44. package/dist/ui/assets/{chunk-4HAMMTFA-Cp59m-71.js → chunk-4HAMMTFA-DXh4eDR_.js} +7 -7
  45. package/dist/ui/assets/chunk-75Z2AOVW-Lw_aAEJj.js +2 -0
  46. package/dist/ui/assets/{chunk-DU6HZSFF-Becd7Cgr.js → chunk-DU6HZSFF-xk3L0f7B.js} +32 -32
  47. package/dist/ui/assets/{chunk-F27PBJKO-Blb2qqJ4.js → chunk-F27PBJKO-Bpl_CvRh.js} +1 -1
  48. package/dist/ui/assets/{chunk-GMAD6QVW-5Qh43abc.js → chunk-GMAD6QVW-BLy3zfAa.js} +6 -6
  49. package/dist/ui/assets/{chunk-GVQU2GXP-Bb0Ur8QB.js → chunk-GVQU2GXP-I3QAn4hA.js} +1 -1
  50. package/dist/ui/assets/{chunk-IMKFNOWR-OYY7Z4BW.js → chunk-IMKFNOWR-BkvAYHDv.js} +5 -5
  51. package/dist/ui/assets/chunk-L3NEJ4N5-B3_3ZyvC.js +1 -0
  52. package/dist/ui/assets/{chunk-OSK3NFVY-DeC-74ju.js → chunk-OSK3NFVY-CSPfQDZp.js} +4 -4
  53. package/dist/ui/assets/{chunk-P2QGCYS3-D9AFqJkh.js → chunk-P2QGCYS3-DDuNAzPy.js} +1 -1
  54. package/dist/ui/assets/chunk-POPQ4Y6H-CWqiokbE.js +1 -0
  55. package/dist/ui/assets/{chunk-PWAF6VOD-DO8Mg8r-.js → chunk-PWAF6VOD-Bh7FA2-4.js} +1 -1
  56. package/dist/ui/assets/{chunk-SHT3W25Y-CoPZM9XW.js → chunk-SHT3W25Y-COKMQSf1.js} +9 -9
  57. package/dist/ui/assets/{chunk-SVP7TREG-Bawvkywu.js → chunk-SVP7TREG-CvMd9Zj2.js} +4 -4
  58. package/dist/ui/assets/{chunk-TICWLB2K-D-QDMLtT.js → chunk-TICWLB2K-aL9gwVQB.js} +6 -6
  59. package/dist/ui/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  60. package/dist/ui/assets/classDiagram-ZZMXUADV-5hxmdbcH.js +1 -0
  61. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-5hxmdbcH.js +1 -0
  62. package/dist/ui/assets/cose-bilkent-JH36ORCC-Cju1UDLh.js +1 -0
  63. package/dist/ui/assets/css-BsVw1vtW.js +1 -0
  64. package/dist/ui/assets/{cynefin-OW5HDTMX-BArHh8-d.js → cynefin-OW5HDTMX-zQf3P8pH.js} +1 -1
  65. package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-CfNzmRAi.js +62 -0
  66. package/dist/ui/assets/{dagre-GXQ25YYZ-9nuP3Mhz.js → dagre-GXQ25YYZ-CDheq0_R.js} +3 -3
  67. package/dist/ui/assets/{diagram-S7CK7UJ4-CcjB4ae6.js → diagram-S7CK7UJ4-BrIlEImS.js} +3 -3
  68. package/dist/ui/assets/diagram-UQ7AKVKN-DLOiVmxh.js +41 -0
  69. package/dist/ui/assets/diagram-VSXAHHWV-CxppTre6.js +3 -0
  70. package/dist/ui/assets/diagram-VX7I27RA-CBdgeQl6.js +24 -0
  71. package/dist/ui/assets/diagram-Z3DM3KII-PpuVwayA.js +24 -0
  72. package/dist/ui/assets/dist-CMahQVbr.js +141 -0
  73. package/dist/ui/assets/dist-DoRUjfaQ.js +12 -0
  74. package/dist/ui/assets/dist-v5Q1xZ2K.js +1 -0
  75. package/dist/ui/assets/ebnfDiagram-PWID7BFC-BLVfeyML.js +1 -0
  76. package/dist/ui/assets/{erDiagram-RLTQ6QDP-eWb4VjRB.js → erDiagram-RLTQ6QDP--wKoyFyZ.js} +6 -6
  77. package/dist/ui/assets/eventmodeling-NTZA5JFV-CrYsvllj.js +1 -0
  78. package/dist/ui/assets/flowDiagram-HODETNUW-C7Br4ITm.js +1 -0
  79. package/dist/ui/assets/ganttDiagram-EL5Y4UJY-DrTipQUC.js +292 -0
  80. package/dist/ui/assets/{gitGraph-4MIJSDKK-BKTHQFNQ.js → gitGraph-4MIJSDKK-DAsPgCmr.js} +1 -1
  81. package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BboA9zPg.js +106 -0
  82. package/dist/ui/assets/github-dark-default-DXG-b-1a.js +1 -0
  83. package/dist/ui/assets/github-light-default-BXViO-2h.js +1 -0
  84. package/dist/ui/assets/go-rLFTqkRN.js +1 -0
  85. package/dist/ui/assets/groovy-CacY0gHj.js +1 -0
  86. package/dist/ui/assets/html-BY76lXLH.js +1 -0
  87. package/dist/ui/assets/{index-DXotWZmz.js → index-BriWELa8.js} +11 -11
  88. package/dist/ui/assets/index-RUa0QB2o.css +1 -0
  89. package/dist/ui/assets/{info-A6RAGUB7-CB_w7eMD.js → info-A6RAGUB7-DBoJACXH.js} +1 -1
  90. package/dist/ui/assets/infoDiagram-27XIBGKW-HmgR08Yy.js +2 -0
  91. package/dist/ui/assets/{ishikawaDiagram-5VMMS53U-Dd1RLJJm.js → ishikawaDiagram-5VMMS53U-B4MzQwJc.js} +1 -1
  92. package/dist/ui/assets/java-BXcb2rRD.js +1 -0
  93. package/dist/ui/assets/javascript-BgS3c2Ky.js +1 -0
  94. package/dist/ui/assets/{journeyDiagram-3NMN7TZE-CD4al8cv.js → journeyDiagram-3NMN7TZE-BvAMPv1w.js} +6 -6
  95. package/dist/ui/assets/json-qhed-kSA.js +1 -0
  96. package/dist/ui/assets/jsonc-CYpm1nAK.js +1 -0
  97. package/dist/ui/assets/jsx-Bz0zcwM4.js +1 -0
  98. package/dist/ui/assets/{kanban-definition-UXKFOSKX-CicP51YB.js → kanban-definition-UXKFOSKX-B6y-zirR.js} +24 -24
  99. package/dist/ui/assets/kotlin-DhhofPvG.js +1 -0
  100. package/dist/ui/assets/{line-Cd1yQwS1.js → line-F8_u2Xou.js} +1 -1
  101. package/dist/ui/assets/{linear-cCCPOpu7.js → linear-C7gIVo4m.js} +1 -1
  102. package/dist/ui/assets/markdown-BYOwaDjH.js +1 -0
  103. package/dist/ui/assets/{mermaid-parser.core-B65nU8-J.js → mermaid-parser.core-BsnCmkcV.js} +3 -3
  104. package/dist/ui/assets/mermaid.core-Xxe8xk1i.js +44 -0
  105. package/dist/ui/assets/{mindmap-definition-YA3MSWOX-B6X7miC7.js → mindmap-definition-YA3MSWOX-Bh1Ybhl5.js} +8 -8
  106. package/dist/ui/assets/{packet-AYTQ26CC-BGs-wvw2.js → packet-AYTQ26CC-ZgwPjY4X.js} +1 -1
  107. package/dist/ui/assets/pegDiagram-XKGWAZYB-DrMCDNF5.js +1 -0
  108. package/dist/ui/assets/{pie-WAS4IAKB-Dk_1-q02.js → pie-WAS4IAKB-DBrPfFPp.js} +1 -1
  109. package/dist/ui/assets/{pieDiagram-E7YTZNPT-g_h8F1NG.js → pieDiagram-E7YTZNPT-bqsPJyZ5.js} +3 -3
  110. package/dist/ui/assets/python-gzcpVVnB.js +1 -0
  111. package/dist/ui/assets/{quadrantDiagram-AXDQQJYC-BZnaapW7.js → quadrantDiagram-AXDQQJYC-x6IUxAPD.js} +6 -6
  112. package/dist/ui/assets/{radar-RG4KPBEZ-DDgd9Igt.js → radar-RG4KPBEZ-C4RwOnXH.js} +1 -1
  113. package/dist/ui/assets/{railroad-74A4TZTK-DhAP39G6.js → railroad-74A4TZTK-B5C8M-MW.js} +1 -1
  114. package/dist/ui/assets/railroad-abnf-HS5TGJTU-xuaYNYsa.js +1 -0
  115. package/dist/ui/assets/railroad-ebnf-LZEXJU2U-D-wtYSuE.js +1 -0
  116. package/dist/ui/assets/railroad-peg-WCYAUIDC-BEUNsbNC.js +1 -0
  117. package/dist/ui/assets/railroadDiagram-O6MQD6OU-Dzch68ki.js +1 -0
  118. package/dist/ui/assets/{requirementDiagram-BXWQKSXE-DgmeoXsi.js → requirementDiagram-BXWQKSXE-C4GbHihu.js} +7 -7
  119. package/dist/ui/assets/rolldown-runtime-hePW80VL.js +1 -0
  120. package/dist/ui/assets/rust-Cfkwpbl8.js +1 -0
  121. package/dist/ui/assets/{sankeyDiagram-P5KCCOFB-DjzQt3qt.js → sankeyDiagram-P5KCCOFB-CU3I4C7t.js} +7 -7
  122. package/dist/ui/assets/{sequenceDiagram-WJ2MYXX4-CbbbJQEL.js → sequenceDiagram-WJ2MYXX4-BsIlljR1.js} +9 -9
  123. package/dist/ui/assets/shellscript-CLZ0U2zV.js +1 -0
  124. package/dist/ui/assets/sql-BsFa4tDR.js +1 -0
  125. package/dist/ui/assets/src-B6xuSHsQ.js +1 -0
  126. package/dist/ui/assets/stateDiagram-D77RDMKH-3U3kk2zw.js +1 -0
  127. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-1AQXnlXU.js +1 -0
  128. package/dist/ui/assets/{swimlanes-42K2YHIH-BsVty5RJ.js → swimlanes-42K2YHIH-B0nfmDPN.js} +1 -1
  129. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-CBW88sps.js +8 -0
  130. package/dist/ui/assets/{timeline-definition-24CTP7MA-jG7c5_Cs.js → timeline-definition-24CTP7MA-QX2EZcsZ.js} +7 -7
  131. package/dist/ui/assets/toml-CcmNWLt0.js +1 -0
  132. package/dist/ui/assets/{treeView-Q6P3EWNA-DLCAW9b3.js → treeView-Q6P3EWNA-ZEpxdDTl.js} +1 -1
  133. package/dist/ui/assets/{treemap-WGGIJYW6-uUXNdPOX.js → treemap-WGGIJYW6-B91l9Icu.js} +1 -1
  134. package/dist/ui/assets/tsx-udAQXfEw.js +1 -0
  135. package/dist/ui/assets/typescript-bsJCZSQ-.js +1 -0
  136. package/dist/ui/assets/{vennDiagram-4TSXK5OY-CHK_fGs0.js → vennDiagram-4TSXK5OY-3VORL03z.js} +7 -7
  137. package/dist/ui/assets/vue-BaXc62bQ.js +1 -0
  138. package/dist/ui/assets/{wardley-WFR3VGLG-DJG6hnMr.js → wardley-WFR3VGLG-DGVR5lOB.js} +1 -1
  139. package/dist/ui/assets/{wardleyDiagram-VM6X3IG4-C82KklcY.js → wardleyDiagram-VM6X3IG4-DcSk5QFM.js} +3 -3
  140. package/dist/ui/assets/{xychartDiagram-S5SC5T6Z-q9hGmKYE.js → xychartDiagram-S5SC5T6Z-B0xjQS8L.js} +6 -6
  141. package/dist/ui/assets/yaml-rwi0_p6S.js +1 -0
  142. package/dist/ui/index.html +2 -2
  143. package/dist/ui/sw.js +2 -2
  144. package/package.json +2 -1
  145. package/dist/ui/assets/ChecksView-CBObmY95.js +0 -1
  146. package/dist/ui/assets/ChecksView-Dquk2SnE.css +0 -1
  147. package/dist/ui/assets/ContextView-5BIYLq1t.js +0 -4
  148. package/dist/ui/assets/DeploymentsView--iIUVfEH.css +0 -1
  149. package/dist/ui/assets/DeploymentsView-AYs3M5WP.js +0 -1
  150. package/dist/ui/assets/DiffView-COhR1P-a.css +0 -1
  151. package/dist/ui/assets/DiffView-elhz-H8B.js +0 -2
  152. package/dist/ui/assets/ReleasesView-6NUvSu9N.css +0 -1
  153. package/dist/ui/assets/ReleasesView-DPt6F5YS.js +0 -3
  154. package/dist/ui/assets/SettingsView-5eZ1Py0Q.js +0 -3
  155. package/dist/ui/assets/WorkView-CFnddFhr.css +0 -1
  156. package/dist/ui/assets/abnfDiagram-VCTEODGH-pHc-qg0W.js +0 -1
  157. package/dist/ui/assets/architecture-7GRP2DOG-BExW7N2X.js +0 -1
  158. package/dist/ui/assets/architectureDiagram-5GKGNRK7-DQV0ZlG2.js +0 -36
  159. package/dist/ui/assets/channel-ZvHJgbXo.js +0 -1
  160. package/dist/ui/assets/chunk-75Z2AOVW-ChHwnZLM.js +0 -2
  161. package/dist/ui/assets/chunk-L3NEJ4N5-aNCeLfta.js +0 -1
  162. package/dist/ui/assets/chunk-POPQ4Y6H-Ba34aN-g.js +0 -1
  163. package/dist/ui/assets/chunk-XXDRQBXY-DFBUG-OT.js +0 -1
  164. package/dist/ui/assets/classDiagram-ZZMXUADV-CmFaEw-m.js +0 -1
  165. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-CmFaEw-m.js +0 -1
  166. package/dist/ui/assets/cose-bilkent-JH36ORCC-BTcgMon1.js +0 -1
  167. package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-DhS-kLot.js +0 -62
  168. package/dist/ui/assets/diagram-UQ7AKVKN-gEbDZ2wA.js +0 -41
  169. package/dist/ui/assets/diagram-VSXAHHWV-B2I7HJ_I.js +0 -3
  170. package/dist/ui/assets/diagram-VX7I27RA-BjZiKmur.js +0 -24
  171. package/dist/ui/assets/diagram-Z3DM3KII-uHuWeWJS.js +0 -24
  172. package/dist/ui/assets/dist-DTg6UBE_.js +0 -1
  173. package/dist/ui/assets/ebnfDiagram-PWID7BFC-Dt6YEtM2.js +0 -1
  174. package/dist/ui/assets/eventmodeling-NTZA5JFV-BGINq340.js +0 -1
  175. package/dist/ui/assets/flowDiagram-HODETNUW-CslflvVm.js +0 -1
  176. package/dist/ui/assets/ganttDiagram-EL5Y4UJY-Dc1YagBo.js +0 -292
  177. package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-5MXnQYI9.js +0 -106
  178. package/dist/ui/assets/index-DWedw2UO.css +0 -1
  179. package/dist/ui/assets/infoDiagram-27XIBGKW-C-9Kuflq.js +0 -2
  180. package/dist/ui/assets/mermaid.core-m8HIJWVk.js +0 -44
  181. package/dist/ui/assets/pegDiagram-XKGWAZYB-C-lyH7_H.js +0 -1
  182. package/dist/ui/assets/railroad-abnf-HS5TGJTU-BqsR_EwF.js +0 -1
  183. package/dist/ui/assets/railroad-ebnf-LZEXJU2U-Duonsle8.js +0 -1
  184. package/dist/ui/assets/railroad-peg-WCYAUIDC-LVUZVuDx.js +0 -1
  185. package/dist/ui/assets/railroadDiagram-O6MQD6OU-CB0apIqD.js +0 -1
  186. package/dist/ui/assets/src-BH-TyZbA.js +0 -1
  187. package/dist/ui/assets/stateDiagram-D77RDMKH-4wOmoi5j.js +0 -1
  188. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BJWDIO8n.js +0 -1
  189. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-DibiQlL8.js +0 -8
@@ -1,4 +1,4 @@
1
1
  {
2
- "hash": "f5bc7080896e6462e45fb88aeecb10c9c2f675395207b58c11bc29b2b5524aa7",
3
- "version": "0.5.49"
2
+ "hash": "f24758813ae7cee389c4a5256fd833c00e64a310a08a11ed6807f1e47cd49919",
3
+ "version": "0.5.50"
4
4
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "generatedAt": "2026-09-20T04:12:23.987Z"
2
+ "generatedAt": "2026-09-20T14:57:13.641Z"
3
3
  }
package/dist/cli/index.js CHANGED
@@ -101,7 +101,7 @@ function help() {
101
101
  cmdRow('new-doc "<desc>"', "Create a document from a description via PM agent"),
102
102
  cmdRow("index [--json]", "Rebuild the derived index cache"),
103
103
  cmdRow("gc [--yes|--dry-run]", "Collect leaked task worktrees/branches (done/absent tasks, integrate candidates)"),
104
- cmdRow("serve [--port N]", "Start the local server (live API + SSE stream)"),
104
+ cmdRow("serve [--port N]", `Start the local server (live API + SSE stream) ${c.dim("flags: --host, --preview-overrides, --no-preview-overrides")}`),
105
105
  cmdRow("stop [--port N]", "Stop this repo's serve process (by its own lockfile)"),
106
106
  cmdRow("service [sub]", `Manage background services ${c.dim("list|status|install|start|stop|restart|enable|disable|remove")}`),
107
107
  cmdRow("tunnel <sub>", `Publish local apps via Cloudflare Tunnel + Zero Trust ${c.dim("(setup|create|allow|deny|rename|destroy|start|install|stop|list|status)")}`),
@@ -40,6 +40,17 @@ export declare function resolveServeHost(explicitHost?: string): {
40
40
  tailscaleDetected: boolean;
41
41
  tailscaleIP?: string;
42
42
  };
43
+ /**
44
+ * Whether this `repoos serve` should apply the repo's preview-only
45
+ * `[preview.*]` config overlay (#0464).
46
+ *
47
+ * Precedence, lowest to highest: the REPOOS_PREVIEW_CHILD=1 marker (set by
48
+ * PreviewManager on every managed preview child) turns it on; an explicit
49
+ * `--no-preview-overrides`/`--preview-overrides` flag always wins. An ordinary
50
+ * `repoos serve` has neither, so it resolves the base configuration unchanged.
51
+ * Exported for tests.
52
+ */
53
+ export declare function resolvePreviewOverrides(args: readonly string[], env?: NodeJS.ProcessEnv): boolean;
43
54
  /**
44
55
  * True when this process is a managed agent (REPOOS_AGENT=1) attempting to
45
56
  * launch `repoos serve` directly, as opposed to a preview child or a reload
@@ -79,6 +79,26 @@ export function resolveServeHost(explicitHost) {
79
79
  return { host: "0.0.0.0", tailscaleDetected: true, tailscaleIP };
80
80
  return { host: "127.0.0.1", tailscaleDetected: false };
81
81
  }
82
+ /**
83
+ * Whether this `repoos serve` should apply the repo's preview-only
84
+ * `[preview.*]` config overlay (#0464).
85
+ *
86
+ * Precedence, lowest to highest: the REPOOS_PREVIEW_CHILD=1 marker (set by
87
+ * PreviewManager on every managed preview child) turns it on; an explicit
88
+ * `--no-preview-overrides`/`--preview-overrides` flag always wins. An ordinary
89
+ * `repoos serve` has neither, so it resolves the base configuration unchanged.
90
+ * Exported for tests.
91
+ */
92
+ export function resolvePreviewOverrides(args, env = process.env) {
93
+ let explicit;
94
+ for (const arg of args) {
95
+ if (arg === "--preview-overrides")
96
+ explicit = true;
97
+ else if (arg === "--no-preview-overrides")
98
+ explicit = false;
99
+ }
100
+ return explicit ?? env.REPOOS_PREVIEW_CHILD === "1";
101
+ }
82
102
  /**
83
103
  * True when this process is a managed agent (REPOOS_AGENT=1) attempting to
84
104
  * launch `repoos serve` directly, as opposed to a preview child or a reload
@@ -116,6 +136,12 @@ export async function cmdServe(args, opts = {}) {
116
136
  else if (args[i] === "--quiet" || args[i] === "-q")
117
137
  quiet = true;
118
138
  }
139
+ // Preview-only config overlay (#0464). A managed preview child
140
+ // (REPOOS_PREVIEW_CHILD=1, set by PreviewManager) applies the repo's
141
+ // `[preview.*]` overlay by default; every ordinary `repoos serve` resolves
142
+ // the base configuration. `--preview-overrides` forces it on (UI-test
143
+ // previews); `--no-preview-overrides` is the escape hatch back to base.
144
+ const applyPreviewOverrides = resolvePreviewOverrides(args);
119
145
  const { host, tailscaleDetected, tailscaleIP } = resolveServeHost(explicitHost);
120
146
  let handle;
121
147
  try {
@@ -124,6 +150,8 @@ export async function cmdServe(args, opts = {}) {
124
150
  handle = await startServer({
125
151
  port,
126
152
  host,
153
+ hostExplicit: explicitHost !== undefined,
154
+ previewOverrides: applyPreviewOverrides,
127
155
  reloadReplacement: process.env.REPOOS_RELOAD === "1",
128
156
  });
129
157
  }
@@ -149,6 +177,11 @@ export async function cmdServe(args, opts = {}) {
149
177
  snap.taskCount +
150
178
  c.dim(" tasks · SSE stream at ") +
151
179
  c.cyan(handle.url + "/api/events"));
180
+ // Report an active preview-only overlay and its effective keys (#0464), so a
181
+ // preview that deliberately differs from the base config is never silent.
182
+ if (handle.previewOverrides?.length) {
183
+ console.log(c.yellow(" preview overrides active: ") + c.dim(handle.previewOverrides.join(", ")));
184
+ }
152
185
  const rt = isBun()
153
186
  ? `Bun ${process.versions.bun ?? ""}`.trim()
154
187
  : `Node ${process.versions.node}`;
@@ -18,7 +18,17 @@ export async function startPreviewServer(root) {
18
18
  // disableAuth: the smoke gate tests generic rendering (title, board,
19
19
  // buttons), not auth flows — a project with [auth] enabled must not make
20
20
  // `repoos check` itself unable to reach the dashboard.
21
- const opts = { host: "127.0.0.1", port: 0, disableAuth: true };
21
+ //
22
+ // previewOverrides: this is the UI-test preview path, so it resolves the same
23
+ // preview-only `[preview.*]` overlay a managed preview applies (#0464). The
24
+ // smoke test's throwaway fixture declares no overlay, so this is normally a
25
+ // no-op; it matters when the harness serves a real root.
26
+ const opts = {
27
+ host: "127.0.0.1",
28
+ port: 0,
29
+ disableAuth: true,
30
+ previewOverrides: true,
31
+ };
22
32
  if (root !== undefined)
23
33
  opts.root = root;
24
34
  return startServer(opts);
@@ -160,7 +160,38 @@ export declare function parseDistributionConfig(parsed: Record<string, unknown>)
160
160
  * Rows without a usable `command` are dropped rather than poisoning resolution.
161
161
  */
162
162
  export declare function parsePreviewConfig(parsed: Record<string, unknown>): PreviewConfig | undefined;
163
- export declare function loadConfig(rootArg?: string): RepoOSConfig;
163
+ export interface PreviewOverlay {
164
+ /** Overridden base config paths (dotted, e.g. `"auth.enabled"`) -> value. */
165
+ entries: Record<string, unknown>;
166
+ /** The overridden paths, sorted, for reporting. */
167
+ keys: string[];
168
+ }
169
+ /**
170
+ * Extract the preview-only overrides from a flat-TOML parse (#0464). A key is
171
+ * an overlay when it sits under `preview.` but is not one of the preview
172
+ * feature's own keys; the path after `preview.` is the base config key it
173
+ * overrides. Because `parseFlatToml` already flattens nested tables, merging is
174
+ * deep by construction: `[preview.auth] enabled = false` contributes only
175
+ * `auth.enabled`, leaving every other `[auth]` key at its base value.
176
+ */
177
+ export declare function parsePreviewOverlays(parsed: Record<string, unknown>): PreviewOverlay;
178
+ /**
179
+ * The preview-only override keys a repo's `repoos.toml` declares that the
180
+ * runtime will actually apply (supported base keys only), sorted. Fail-soft: a
181
+ * missing/unreadable file yields `[]`. Used by the preview manager to report
182
+ * the effective overrides a preview boot is applying (#0464) — the child itself
183
+ * warns about and drops the same unknown paths.
184
+ */
185
+ export declare function readPreviewOverlayKeys(root: string): string[];
186
+ export interface LoadConfigOptions {
187
+ /**
188
+ * Apply the repo's `[preview.*]` configuration overlay (#0464). Only the
189
+ * preview/UI-test preview runtime sets this; every normal command leaves it
190
+ * unset and resolves the base configuration unchanged.
191
+ */
192
+ previewOverrides?: boolean;
193
+ }
194
+ export declare function loadConfig(rootArg?: string, options?: LoadConfigOptions): RepoOSConfig;
164
195
  /** Metadata describing a single config field for the Settings UI. */
165
196
  export interface ConfigFieldMeta {
166
197
  key: string;
@@ -655,7 +655,65 @@ function normalizeReadyTimeoutMs(value) {
655
655
  return undefined;
656
656
  return value;
657
657
  }
658
- export function loadConfig(rootArg) {
658
+ /**
659
+ * The `[preview]` keys that configure *how a preview boots* — the preview
660
+ * feature's own settings. Any other `[preview.<path>]` table is a preview-only
661
+ * override of the base configuration (#0464), not a preview setting.
662
+ */
663
+ const PREVIEW_FEATURE_KEYS = new Set(["command", "cwd", "readyPath", "readyTimeoutMs", "targets"]);
664
+ /**
665
+ * Extract the preview-only overrides from a flat-TOML parse (#0464). A key is
666
+ * an overlay when it sits under `preview.` but is not one of the preview
667
+ * feature's own keys; the path after `preview.` is the base config key it
668
+ * overrides. Because `parseFlatToml` already flattens nested tables, merging is
669
+ * deep by construction: `[preview.auth] enabled = false` contributes only
670
+ * `auth.enabled`, leaving every other `[auth]` key at its base value.
671
+ */
672
+ export function parsePreviewOverlays(parsed) {
673
+ const entries = {};
674
+ for (const [key, value] of Object.entries(parsed)) {
675
+ if (!key.startsWith("preview."))
676
+ continue;
677
+ const path = key.slice("preview.".length);
678
+ const head = path.split(".")[0];
679
+ if (PREVIEW_FEATURE_KEYS.has(head))
680
+ continue;
681
+ if (typeof value === "object" && value !== null)
682
+ continue; // no table arrays
683
+ entries[path] = value;
684
+ }
685
+ const keys = Object.keys(entries).sort();
686
+ return { entries, keys };
687
+ }
688
+ /**
689
+ * True when `path` names a base configuration key RepoOS actually reads, so an
690
+ * overlay targeting it is meaningful. `SUPPORTED_TOML_KEYS` (the same contract
691
+ * the docs-drift test and `repoos doctor` use) lists the dotted leaves, so a
692
+ * nested override like `auth.emailProvider.type` resolves while a typo or a
693
+ * section name is dropped with a warning.
694
+ */
695
+ function isOverridableConfigPath(path) {
696
+ return SUPPORTED_TOML_KEYS.includes(path);
697
+ }
698
+ /**
699
+ * The preview-only override keys a repo's `repoos.toml` declares that the
700
+ * runtime will actually apply (supported base keys only), sorted. Fail-soft: a
701
+ * missing/unreadable file yields `[]`. Used by the preview manager to report
702
+ * the effective overrides a preview boot is applying (#0464) — the child itself
703
+ * warns about and drops the same unknown paths.
704
+ */
705
+ export function readPreviewOverlayKeys(root) {
706
+ const tomlPath = join(root, "repoos.toml");
707
+ if (!existsSync(tomlPath))
708
+ return [];
709
+ try {
710
+ return parsePreviewOverlays(parseFlatToml(readFileSync(tomlPath, "utf8"))).keys.filter(isOverridableConfigPath);
711
+ }
712
+ catch {
713
+ return [];
714
+ }
715
+ }
716
+ export function loadConfig(rootArg, options = {}) {
659
717
  const root = rootArg ? resolve(rootArg) : findRepoRoot();
660
718
  // Load .env before resolving [auth]/[whisper] secrets below, so every path
661
719
  // that boots a real server (repoos serve, previews, the UI smoke test)
@@ -666,6 +724,27 @@ export function loadConfig(rootArg) {
666
724
  const tomlPath = join(root, "repoos.toml");
667
725
  if (existsSync(tomlPath)) {
668
726
  const parsed = parseFlatToml(readFileSync(tomlPath, "utf8"));
727
+ // Preview-only overlay (#0464): re-apply the `[preview.*]` keys over the
728
+ // base parse before the normal field reads below, so precedence is
729
+ // defaults → base repoos.toml → preview overlay → explicit CLI flags. Only
730
+ // the preview/UI-test runtime opts in; every other caller sees the base
731
+ // config. An overlay path RepoOS does not read is dropped with a warning
732
+ // rather than silently accepted as a typo.
733
+ const appliedOverrides = [];
734
+ if (options.previewOverrides) {
735
+ const overlay = parsePreviewOverlays(parsed);
736
+ for (const [path, value] of Object.entries(overlay.entries)) {
737
+ if (!isOverridableConfigPath(path)) {
738
+ console.warn(`[preview] ignoring unknown preview override "${path}"`);
739
+ continue;
740
+ }
741
+ parsed[path] = value;
742
+ appliedOverrides.push(path);
743
+ }
744
+ appliedOverrides.sort();
745
+ if (appliedOverrides.length)
746
+ cfg.previewOverrides = appliedOverrides;
747
+ }
669
748
  const get = (k) => parsed[k] ?? parsed[`repoos.${k}`];
670
749
  if (typeof get("workDir") === "string")
671
750
  cfg.workDir = get("workDir");
@@ -1395,6 +1474,10 @@ export const SUPPORTED_TOML_KEYS = [
1395
1474
  "preview.targets.cwd",
1396
1475
  "preview.targets.readyPath",
1397
1476
  "preview.targets.readyTimeoutMs",
1477
+ // Preview-only overrides (#0464): a `[preview.<base path>]` table applied
1478
+ // only by the preview/UI-test preview runtime. auth.enabled is the headline
1479
+ // case; any supported base key can be overridden the same way.
1480
+ "preview.auth.enabled",
1398
1481
  // Checks
1399
1482
  "check.uiSmoke",
1400
1483
  "check.uiStylesheet",
@@ -1,3 +1,4 @@
1
+ import { type LoadConfigOptions } from "./config.js";
1
2
  import { ORIGINAL_PROMPT_HEADING } from "./task.js";
2
3
  import { type CommitNewFileResult } from "./git.js";
3
4
  import { type RepoOSConfig, type RepoIndex, type Task, type Status } from "./types.js";
@@ -19,6 +20,17 @@ export interface CreateTaskInput {
19
20
  * capture is never lost, even if a later agent pass rewrites the body.
20
21
  */
21
22
  originalPrompt?: string;
23
+ /**
24
+ * Per-task PM agent assignment persisted at creation (#0461). The freeform
25
+ * pane's picker chooses the PM agent/model for the one-off flesh-out run;
26
+ * these carry that same selection into the task's frontmatter so later PM
27
+ * actions (reply-from-context, re-flesh-out, restart) keep it. Only values
28
+ * that differ from the configured PM default are set — `null` means "use the
29
+ * configured default", matching the PM tab's own save logic.
30
+ */
31
+ pmAgentOverride?: string | null;
32
+ pmCliOverride?: string | null;
33
+ pmModelOverride?: string | null;
22
34
  }
23
35
  export { ORIGINAL_PROMPT_HEADING };
24
36
  /**
@@ -56,6 +68,6 @@ export interface RepoOS {
56
68
  /** Surgically commit a single new file (fail-soft; never touches other files). */
57
69
  commitNewFile(absPath: string, message: string): CommitNewFileResult;
58
70
  }
59
- export declare function createRepoOS(root?: string): RepoOS;
71
+ export declare function createRepoOS(root?: string, loadOptions?: LoadConfigOptions): RepoOS;
60
72
  export * from "./types.js";
61
73
  export { loadConfig, findRepoRoot } from "./config.js";
@@ -45,8 +45,8 @@ _What should the end experience be?_
45
45
 
46
46
  _Constraints, files to touch, things NOT to do._
47
47
  `;
48
- export function createRepoOS(root) {
49
- const config = loadConfig(root);
48
+ export function createRepoOS(root, loadOptions = {}) {
49
+ const config = loadConfig(root, loadOptions);
50
50
  function freshIndex() {
51
51
  return buildIndex(config);
52
52
  }
@@ -188,9 +188,9 @@ export function createRepoOS(root) {
188
188
  agentOverride: null,
189
189
  cliOverride: null,
190
190
  modelOverride: null,
191
- pmAgentOverride: null,
192
- pmCliOverride: null,
193
- pmModelOverride: null,
191
+ pmAgentOverride: input.pmAgentOverride ?? null,
192
+ pmCliOverride: input.pmCliOverride ?? null,
193
+ pmModelOverride: input.pmModelOverride ?? null,
194
194
  reviewAgentOverride: null,
195
195
  reviewCliOverride: null,
196
196
  reviewModelOverride: null,
@@ -407,6 +407,14 @@ export interface RepoOSConfig {
407
407
  * result rather than booting RepoOS's own board.
408
408
  */
409
409
  preview?: PreviewConfig;
410
+ /**
411
+ * Preview-only config overrides that were applied (task #0464), as sorted
412
+ * dotted base key paths (e.g. `["auth.enabled"]`). Set only when config was
413
+ * resolved with the preview overlay turned on — the preview/UI-test preview
414
+ * runtime does this; every normal command resolves the base config and leaves
415
+ * this undefined. Runtime information, not a `repoos.toml` field of its own.
416
+ */
417
+ previewOverrides?: string[];
410
418
  /**
411
419
  * Per-project task-worktree behavior (#0373). Omitted means defaults — in
412
420
  * particular, no `.env` is placed in any worktree.
@@ -104,6 +104,17 @@ export declare function resetForeignWorkFiles(opts: {
104
104
  * already rejects an empty merge that actually swallowed real branch work.
105
105
  */
106
106
  export declare function isDocsOnlyChange(paths: string[], docsDir?: string): boolean;
107
+ /**
108
+ * Does a merged candidate declare a dependency tree that may differ from the
109
+ * one already installed in main?
110
+ *
111
+ * Candidates normally symlink main's node_modules for a warm, cheap gate. A
112
+ * feature that adds or changes a package cannot safely use that tree: it may
113
+ * compile in its own worktree but fail after the merge because main has not
114
+ * installed the new dependency yet (#0449). Treat package manifests and every
115
+ * conventional JavaScript lockfile as an exact, conservative boundary.
116
+ */
117
+ export declare function hasDependencyInputChange(paths: readonly string[]): boolean;
107
118
  /**
108
119
  * The useful part of a failed command's combined output. bun/npm wrap a child
109
120
  * failure with a generic trailing line (`error: script "repoos" exited with
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Phases track recovery: if interrupted mid-flight, retry resumes from the current phase.
9
9
  */
10
- import { readFileSync, existsSync, symlinkSync, readdirSync, mkdirSync, writeFileSync, } from "node:fs";
10
+ import { readFileSync, existsSync, lstatSync, symlinkSync, unlinkSync, readdirSync, mkdirSync, writeFileSync, } from "node:fs";
11
11
  import { join, relative } from "node:path";
12
12
  import { spawn } from "node:child_process";
13
13
  import { currentBranch, runGit, worktreePathForBranch, ensureWorktree, removeWorktree, deleteBranch, pruneWorktrees, isGitRepo, commitDirtyFiles, mergeBranch, dirtyFiles, getDiff, getDiffStats, getChangedFilePaths, GitDirtyCheckError, } from "../core/git.js";
@@ -207,6 +207,26 @@ export function isDocsOnlyChange(paths, docsDir = "docs") {
207
207
  const docsPrefix = `${docsDir.replace(/\/+$/, "")}/`;
208
208
  return paths.every((p) => p.startsWith(docsPrefix) || p.endsWith(".md"));
209
209
  }
210
+ /**
211
+ * Does a merged candidate declare a dependency tree that may differ from the
212
+ * one already installed in main?
213
+ *
214
+ * Candidates normally symlink main's node_modules for a warm, cheap gate. A
215
+ * feature that adds or changes a package cannot safely use that tree: it may
216
+ * compile in its own worktree but fail after the merge because main has not
217
+ * installed the new dependency yet (#0449). Treat package manifests and every
218
+ * conventional JavaScript lockfile as an exact, conservative boundary.
219
+ */
220
+ export function hasDependencyInputChange(paths) {
221
+ return paths.some((path) => {
222
+ const filename = path.slice(path.lastIndexOf("/") + 1);
223
+ return (filename === "package.json" ||
224
+ filename === "bun.lock" ||
225
+ filename === "package-lock.json" ||
226
+ filename === "pnpm-lock.yaml" ||
227
+ filename === "yarn.lock");
228
+ });
229
+ }
210
230
  /**
211
231
  * Resolve the repository's actual default branch name.
212
232
  * Tries (in order):
@@ -373,6 +393,54 @@ function runProcess(cmd, args, opts) {
373
393
  function commandMissing(res) {
374
394
  return res.errorCode === "ENOENT" || res.errorCode === "EACCES";
375
395
  }
396
+ /**
397
+ * Turn a candidate's shared node_modules link into a private, lockfile-exact
398
+ * install after its merge changed package inputs. Never run this against main:
399
+ * doing so would mutate the shared install to match code that has not passed
400
+ * the gate yet.
401
+ */
402
+ async function prepareCandidateDependencies(candidatePath, isCancelled) {
403
+ const nodeModules = join(candidatePath, "node_modules");
404
+ try {
405
+ // A normal candidate reuses main's tree through this link. Removing only
406
+ // the link leaves main completely untouched; the frozen install below then
407
+ // creates a candidate-local tree from the merged lockfile.
408
+ if (lstatSync(nodeModules).isSymbolicLink())
409
+ unlinkSync(nodeModules);
410
+ }
411
+ catch {
412
+ /* Missing or unreadable node_modules is fine: the install recreates it. */
413
+ }
414
+ const commands = existsSync(join(candidatePath, "bun.lock"))
415
+ ? [{ command: "bun", args: ["install", "--frozen-lockfile"] }]
416
+ : existsSync(join(candidatePath, "pnpm-lock.yaml"))
417
+ ? [{ command: "pnpm", args: ["install", "--frozen-lockfile"] }]
418
+ : existsSync(join(candidatePath, "package-lock.json"))
419
+ ? [{ command: "npm", args: ["ci"] }]
420
+ : existsSync(join(candidatePath, "yarn.lock"))
421
+ ? [{ command: "yarn", args: ["install", "--frozen-lockfile"] }]
422
+ : [];
423
+ if (commands.length === 0) {
424
+ return {
425
+ ok: false,
426
+ reason: "package inputs changed but no recognized lockfile is available to prepare candidate dependencies",
427
+ };
428
+ }
429
+ const { command, args } = commands[0];
430
+ const result = await runProcess(command, args, {
431
+ cwd: candidatePath,
432
+ timeout: 300_000,
433
+ isCancelled,
434
+ });
435
+ if (result.cancelled)
436
+ return { ok: false, cancelled: true };
437
+ if (result.status === 0)
438
+ return { ok: true };
439
+ const detail = commandMissing(result)
440
+ ? `${command} is not available to prepare candidate dependencies`
441
+ : tailLine(result.stdout, result.stderr);
442
+ return { ok: false, reason: `dependency install failed: ${detail}` };
443
+ }
376
444
  /** Candidate validation and publication orchestrator for one job. */
377
445
  export class CloseOutOrchestrator {
378
446
  config;
@@ -1030,6 +1098,24 @@ export class CloseOutOrchestrator {
1030
1098
  this.logger?.integration(job.taskId, "info", "docs-only candidate — skipping the full build + check gate (no code/source paths changed)", { paths: changedPaths });
1031
1099
  }
1032
1100
  else {
1101
+ // The candidate normally points at main's node_modules to avoid a cold
1102
+ // install. That tree cannot satisfy a dependency added by this branch,
1103
+ // however, because main has not merged its package.json/lockfile yet.
1104
+ // Give only dependency-changing candidates their own frozen install.
1105
+ if (changedPaths !== null && hasDependencyInputChange(changedPaths)) {
1106
+ this.onProgress?.("build");
1107
+ const dependencies = await prepareCandidateDependencies(wtPath, () => this.isCancelled(job.taskId));
1108
+ if (dependencies.cancelled) {
1109
+ return { ok: false, cancelled: true, reason: CANCEL_REASON };
1110
+ }
1111
+ if (!dependencies.ok) {
1112
+ return {
1113
+ ok: false,
1114
+ retryable: !dependencies.reason?.startsWith("package inputs changed"),
1115
+ reason: dependencies.reason ?? "could not prepare candidate dependencies",
1116
+ };
1117
+ }
1118
+ }
1033
1119
  // Run the post-merge gate: build + check via bun/npm.
1034
1120
  this.onProgress?.("build");
1035
1121
  let buildRes = await runProcess("bun", ["run", "build"], {
@@ -29,6 +29,13 @@ export interface PreviewInfo {
29
29
  * shell's whole tree down with it.
30
30
  */
31
31
  processGroup?: boolean;
32
+ /**
33
+ * Preview-only config override keys (#0464) the worktree's `repoos.toml`
34
+ * declares, as sorted dotted base-key paths (e.g. `["auth.enabled"]`). The
35
+ * child applies them because PreviewManager spawns it with
36
+ * REPOOS_PREVIEW_CHILD=1; empty/absent means the preview runs the base config.
37
+ */
38
+ overrides?: string[];
32
39
  }
33
40
  export interface PreviewResult {
34
41
  ok: boolean;
@@ -38,6 +45,8 @@ export interface PreviewResult {
38
45
  readyPath?: string;
39
46
  /** Which preview target ran (#0362 review) — see `PreviewInfo.label`. */
40
47
  label?: string;
48
+ /** Preview-only config override keys this preview applied (#0464). */
49
+ overrides?: string[];
41
50
  error?: string;
42
51
  }
43
52
  /** Result of a trusted server-side health/static probe of a preview URL (#0121). */
@@ -20,6 +20,7 @@ import { spawn, execFileSync } from "node:child_process";
20
20
  import { createServer as createTcpServer } from "node:net";
21
21
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
22
22
  import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
23
+ import { readPreviewOverlayKeys } from "../core/config.js";
23
24
  import { linkInheritedEnv, worktreePathForBranch } from "../core/git.js";
24
25
  const PREVIEW_STATES = ["active", "review"];
25
26
  const HOST = "127.0.0.1";
@@ -380,6 +381,7 @@ export class PreviewManager {
380
381
  url: existing.url,
381
382
  readyPath: existing.readyPath,
382
383
  label: existing.label,
384
+ ...(existing.overrides?.length ? { overrides: existing.overrides } : {}),
383
385
  };
384
386
  }
385
387
  // Concurrent starts for the same task (e.g. duplicate transition events)
@@ -427,6 +429,12 @@ export class PreviewManager {
427
429
  // fail-soft; on a worktree that already has it (or a repo that didn't opt
428
430
  // in) this is a no-op.
429
431
  linkInheritedEnv(this.config.root, root);
432
+ // Preview-only config overrides (#0464): the worktree's own `[preview.*]`
433
+ // keys. The child is spawned with REPOOS_PREVIEW_CHILD=1 below, so a
434
+ // `repoos serve` preview applies them; reporting them here makes the
435
+ // deliberate divergence from base config visible even though the child's
436
+ // console is not attached.
437
+ const overrides = readPreviewOverlayKeys(root);
430
438
  // Decide how to preview this task (#0362): a project-declared command
431
439
  // selected by area. A task whose area matches no configured target — or a
432
440
  // project with no `[preview]` config at all (#0370) — returns a clear
@@ -472,10 +480,12 @@ export class PreviewManager {
472
480
  label: target.label,
473
481
  ...(spawned.command ? { command: spawned.command } : {}),
474
482
  ...(spawned.processGroup ? { processGroup: true } : {}),
483
+ ...(overrides.length ? { overrides } : {}),
475
484
  };
476
485
  this.registry.set(task.id, info);
477
486
  this.persist();
478
- this.logLifecycle("started", task.id, `target=${info.label} url=${info.url} pid=${info.pid} port=${info.port}`);
487
+ this.logLifecycle("started", task.id, `target=${info.label} url=${info.url} pid=${info.pid} port=${info.port}` +
488
+ (overrides.length ? ` overrides=${overrides.join(",")}` : ""));
479
489
  this.emit({
480
490
  type: "preview",
481
491
  id: task.id,
@@ -488,6 +498,7 @@ export class PreviewManager {
488
498
  url: info.url,
489
499
  readyPath: target.readyPath,
490
500
  label: info.label,
501
+ ...(overrides.length ? { overrides } : {}),
491
502
  };
492
503
  }
493
504
  /** Stop a task's preview. Idempotent: stopping nothing is a no-op success. */
@@ -9,3 +9,15 @@ export declare const getSupportBundlePreview: RouteHandler;
9
9
  * response only contains the manifest and the local path. Nothing is uploaded.
10
10
  */
11
11
  export declare const createSupportBundle: RouteHandler;
12
+ /**
13
+ * Reveal an existing support archive in the machine's file browser. The
14
+ * browser supplies a path, but the server only ever opens a real archive
15
+ * directly below this repo's own `.repoos/support/` directory.
16
+ */
17
+ export declare const revealSupportBundle: RouteHandler;
18
+ /**
19
+ * Generate an editable bug report or feature request from a user's notes using
20
+ * the configured PM agent. The report stays entirely local — nothing is uploaded.
21
+ * Attachments are intentionally excluded from the PM input (0463).
22
+ */
23
+ export declare const generateBugReport: RouteHandler;