rivet-design 0.17.4 → 0.17.5

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 (798) hide show
  1. package/bin/rivet.js +0 -16
  2. package/dist/agent-variants/SessionStore.d.ts +0 -239
  3. package/dist/agent-variants/SessionStore.d.ts.map +1 -1
  4. package/dist/agent-variants/SessionStore.js +10 -368
  5. package/dist/agent-variants/SessionStore.js.map +1 -1
  6. package/dist/agent-variants/VariantWorkspaceManager.d.ts +0 -10
  7. package/dist/agent-variants/VariantWorkspaceManager.d.ts.map +1 -1
  8. package/dist/agent-variants/VariantWorkspaceManager.js +0 -17
  9. package/dist/agent-variants/VariantWorkspaceManager.js.map +1 -1
  10. package/dist/agent-variants/WorkerExecutorService.d.ts +1 -105
  11. package/dist/agent-variants/WorkerExecutorService.d.ts.map +1 -1
  12. package/dist/agent-variants/WorkerExecutorService.js +11 -182
  13. package/dist/agent-variants/WorkerExecutorService.js.map +1 -1
  14. package/dist/agent-variants/WorktreeOrchestrator.d.ts +0 -597
  15. package/dist/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
  16. package/dist/agent-variants/WorktreeOrchestrator.js +4 -1273
  17. package/dist/agent-variants/WorktreeOrchestrator.js.map +1 -1
  18. package/dist/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +0 -6
  19. package/dist/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
  20. package/dist/agent-variants/WorktreeOrchestrator.testHelpers.js +0 -23
  21. package/dist/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
  22. package/dist/agent-variants/briefContent.d.ts +0 -11
  23. package/dist/agent-variants/briefContent.d.ts.map +1 -1
  24. package/dist/agent-variants/briefContent.js +0 -12
  25. package/dist/agent-variants/briefContent.js.map +1 -1
  26. package/dist/agent-variants/contextAssets.d.ts +0 -3
  27. package/dist/agent-variants/contextAssets.d.ts.map +1 -1
  28. package/dist/agent-variants/contextAssets.js +0 -3
  29. package/dist/agent-variants/contextAssets.js.map +1 -1
  30. package/dist/agent-variants/contracts.d.ts +4 -492
  31. package/dist/agent-variants/contracts.d.ts.map +1 -1
  32. package/dist/agent-variants/contracts.js +0 -165
  33. package/dist/agent-variants/contracts.js.map +1 -1
  34. package/dist/agent-variants/createProjectArtifacts.d.ts +0 -17
  35. package/dist/agent-variants/createProjectArtifacts.d.ts.map +1 -1
  36. package/dist/agent-variants/createProjectArtifacts.js +0 -10
  37. package/dist/agent-variants/createProjectArtifacts.js.map +1 -1
  38. package/dist/agent-variants/diffQa.d.ts +0 -1
  39. package/dist/agent-variants/diffQa.d.ts.map +1 -1
  40. package/dist/agent-variants/diffQa.js +0 -1
  41. package/dist/agent-variants/diffQa.js.map +1 -1
  42. package/dist/agent-variants/directionAuthoring.d.ts +0 -13
  43. package/dist/agent-variants/directionAuthoring.d.ts.map +1 -1
  44. package/dist/agent-variants/directionAuthoring.js +12 -46
  45. package/dist/agent-variants/directionAuthoring.js.map +1 -1
  46. package/dist/agent-variants/elementRefToTarget.d.ts +0 -17
  47. package/dist/agent-variants/elementRefToTarget.d.ts.map +1 -1
  48. package/dist/agent-variants/elementRefToTarget.js +0 -17
  49. package/dist/agent-variants/elementRefToTarget.js.map +1 -1
  50. package/dist/agent-variants/generatedDestination.d.ts +0 -3
  51. package/dist/agent-variants/generatedDestination.d.ts.map +1 -1
  52. package/dist/agent-variants/generatedDestination.js +0 -3
  53. package/dist/agent-variants/generatedDestination.js.map +1 -1
  54. package/dist/agent-variants/previewQa.d.ts +0 -6
  55. package/dist/agent-variants/previewQa.d.ts.map +1 -1
  56. package/dist/agent-variants/previewQa.js +0 -5
  57. package/dist/agent-variants/previewQa.js.map +1 -1
  58. package/dist/agent-variants/runLabel.d.ts +0 -15
  59. package/dist/agent-variants/runLabel.d.ts.map +1 -1
  60. package/dist/agent-variants/runLabel.js +0 -19
  61. package/dist/agent-variants/runLabel.js.map +1 -1
  62. package/dist/agent-variants/runPlan.d.ts +3 -84
  63. package/dist/agent-variants/runPlan.d.ts.map +1 -1
  64. package/dist/agent-variants/runPlan.js +0 -51
  65. package/dist/agent-variants/runPlan.js.map +1 -1
  66. package/dist/agent-variants/sourceContext.d.ts +0 -10
  67. package/dist/agent-variants/sourceContext.d.ts.map +1 -1
  68. package/dist/agent-variants/sourceContext.js +0 -36
  69. package/dist/agent-variants/sourceContext.js.map +1 -1
  70. package/dist/agent-variants/variantContext.d.ts +0 -6
  71. package/dist/agent-variants/variantContext.d.ts.map +1 -1
  72. package/dist/agent-variants/variantContext.js +0 -9
  73. package/dist/agent-variants/variantContext.js.map +1 -1
  74. package/dist/agent-variants/videoKeyframes.d.ts +0 -7
  75. package/dist/agent-variants/videoKeyframes.d.ts.map +1 -1
  76. package/dist/agent-variants/videoKeyframes.js +0 -7
  77. package/dist/agent-variants/videoKeyframes.js.map +1 -1
  78. package/dist/agent-variants/workItemBriefing.d.ts +0 -21
  79. package/dist/agent-variants/workItemBriefing.d.ts.map +1 -1
  80. package/dist/agent-variants/workItemBriefing.js +0 -49
  81. package/dist/agent-variants/workItemBriefing.js.map +1 -1
  82. package/dist/agent-variants/workerRuntime.d.ts +1 -137
  83. package/dist/agent-variants/workerRuntime.d.ts.map +1 -1
  84. package/dist/agent-variants/workerRuntime.js +8 -147
  85. package/dist/agent-variants/workerRuntime.js.map +1 -1
  86. package/dist/cli/browser.d.ts +0 -1
  87. package/dist/cli/browser.d.ts.map +1 -1
  88. package/dist/cli/browser.js +0 -1
  89. package/dist/cli/browser.js.map +1 -1
  90. package/dist/cli/callerRunnerPaths.d.ts +0 -50
  91. package/dist/cli/callerRunnerPaths.d.ts.map +1 -1
  92. package/dist/cli/callerRunnerPaths.js +0 -59
  93. package/dist/cli/callerRunnerPaths.js.map +1 -1
  94. package/dist/cli/client.d.ts +0 -18
  95. package/dist/cli/client.d.ts.map +1 -1
  96. package/dist/cli/client.js +0 -28
  97. package/dist/cli/client.js.map +1 -1
  98. package/dist/cli/commandNames.d.ts +0 -7
  99. package/dist/cli/commandNames.d.ts.map +1 -1
  100. package/dist/cli/commandNames.js +0 -7
  101. package/dist/cli/commandNames.js.map +1 -1
  102. package/dist/cli/commands/auth.d.ts +0 -6
  103. package/dist/cli/commands/auth.d.ts.map +1 -1
  104. package/dist/cli/commands/auth.js +0 -6
  105. package/dist/cli/commands/auth.js.map +1 -1
  106. package/dist/cli/commands/elementSelector.d.ts +0 -6
  107. package/dist/cli/commands/elementSelector.d.ts.map +1 -1
  108. package/dist/cli/commands/elementSelector.js +0 -7
  109. package/dist/cli/commands/elementSelector.js.map +1 -1
  110. package/dist/cli/commands/evidence.d.ts +0 -6
  111. package/dist/cli/commands/evidence.d.ts.map +1 -1
  112. package/dist/cli/commands/evidence.js +0 -6
  113. package/dist/cli/commands/evidence.js.map +1 -1
  114. package/dist/cli/commands/libraryOpen.d.ts +0 -1
  115. package/dist/cli/commands/libraryOpen.d.ts.map +1 -1
  116. package/dist/cli/commands/libraryOpen.js +0 -4
  117. package/dist/cli/commands/libraryOpen.js.map +1 -1
  118. package/dist/cli/commands/mcpServe.d.ts +0 -24
  119. package/dist/cli/commands/mcpServe.d.ts.map +1 -1
  120. package/dist/cli/commands/mcpServe.js +31 -102
  121. package/dist/cli/commands/mcpServe.js.map +1 -1
  122. package/dist/cli/commands/open.d.ts +0 -8
  123. package/dist/cli/commands/open.d.ts.map +1 -1
  124. package/dist/cli/commands/open.js +0 -57
  125. package/dist/cli/commands/open.js.map +1 -1
  126. package/dist/cli/commands/reference.d.ts +0 -5
  127. package/dist/cli/commands/reference.d.ts.map +1 -1
  128. package/dist/cli/commands/reference.js +0 -27
  129. package/dist/cli/commands/reference.js.map +1 -1
  130. package/dist/cli/commands/serve.d.ts +0 -5
  131. package/dist/cli/commands/serve.d.ts.map +1 -1
  132. package/dist/cli/commands/serve.js +0 -34
  133. package/dist/cli/commands/serve.js.map +1 -1
  134. package/dist/cli/commands/shared.d.ts +0 -16
  135. package/dist/cli/commands/shared.d.ts.map +1 -1
  136. package/dist/cli/commands/shared.js +0 -19
  137. package/dist/cli/commands/shared.js.map +1 -1
  138. package/dist/cli/commands/status.d.ts +0 -6
  139. package/dist/cli/commands/status.d.ts.map +1 -1
  140. package/dist/cli/commands/status.js +0 -11
  141. package/dist/cli/commands/status.js.map +1 -1
  142. package/dist/cli/commands/stop.d.ts +0 -5
  143. package/dist/cli/commands/stop.d.ts.map +1 -1
  144. package/dist/cli/commands/stop.js +0 -6
  145. package/dist/cli/commands/stop.js.map +1 -1
  146. package/dist/cli/commands/update.d.ts +0 -1
  147. package/dist/cli/commands/update.d.ts.map +1 -1
  148. package/dist/cli/commands/update.js +0 -1
  149. package/dist/cli/commands/update.js.map +1 -1
  150. package/dist/cli/commands/variants.d.ts +0 -1
  151. package/dist/cli/commands/variants.d.ts.map +1 -1
  152. package/dist/cli/commands/variants.js +0 -31
  153. package/dist/cli/commands/variants.js.map +1 -1
  154. package/dist/cli/commands/wait.d.ts +0 -21
  155. package/dist/cli/commands/wait.d.ts.map +1 -1
  156. package/dist/cli/commands/wait.js +0 -23
  157. package/dist/cli/commands/wait.js.map +1 -1
  158. package/dist/cli/entry.d.ts +0 -10
  159. package/dist/cli/entry.d.ts.map +1 -1
  160. package/dist/cli/entry.js +0 -13
  161. package/dist/cli/entry.js.map +1 -1
  162. package/dist/cli/envelope.d.ts +1 -25
  163. package/dist/cli/envelope.d.ts.map +1 -1
  164. package/dist/cli/envelope.js +0 -19
  165. package/dist/cli/envelope.js.map +1 -1
  166. package/dist/cli/flags.d.ts +0 -7
  167. package/dist/cli/flags.d.ts.map +1 -1
  168. package/dist/cli/flags.js +0 -7
  169. package/dist/cli/flags.js.map +1 -1
  170. package/dist/cli/handoff.d.ts +0 -33
  171. package/dist/cli/handoff.d.ts.map +1 -1
  172. package/dist/cli/handoff.js +0 -42
  173. package/dist/cli/handoff.js.map +1 -1
  174. package/dist/cli/handoffStore.d.ts +0 -11
  175. package/dist/cli/handoffStore.d.ts.map +1 -1
  176. package/dist/cli/handoffStore.js +0 -10
  177. package/dist/cli/handoffStore.js.map +1 -1
  178. package/dist/cli/hostWorkNextAction.d.ts +0 -11
  179. package/dist/cli/hostWorkNextAction.d.ts.map +1 -1
  180. package/dist/cli/hostWorkNextAction.js +0 -4
  181. package/dist/cli/hostWorkNextAction.js.map +1 -1
  182. package/dist/cli/io.d.ts +0 -9
  183. package/dist/cli/io.d.ts.map +1 -1
  184. package/dist/cli/io.js +0 -1
  185. package/dist/cli/io.js.map +1 -1
  186. package/dist/cli/resolveDefaultNodeEnv.d.ts +0 -5
  187. package/dist/cli/resolveDefaultNodeEnv.d.ts.map +1 -1
  188. package/dist/cli/resolveDefaultNodeEnv.js +0 -5
  189. package/dist/cli/resolveDefaultNodeEnv.js.map +1 -1
  190. package/dist/cli/router.d.ts +0 -21
  191. package/dist/cli/router.d.ts.map +1 -1
  192. package/dist/cli/router.js +0 -46
  193. package/dist/cli/router.js.map +1 -1
  194. package/dist/cli/runnerSelection.d.ts +0 -58
  195. package/dist/cli/runnerSelection.d.ts.map +1 -1
  196. package/dist/cli/runnerSelection.js +0 -16
  197. package/dist/cli/runnerSelection.js.map +1 -1
  198. package/dist/cli/serverHandshake.d.ts +0 -36
  199. package/dist/cli/serverHandshake.d.ts.map +1 -1
  200. package/dist/cli/serverHandshake.js +0 -29
  201. package/dist/cli/serverHandshake.js.map +1 -1
  202. package/dist/cli/serverUnavailable.d.ts +0 -1
  203. package/dist/cli/serverUnavailable.d.ts.map +1 -1
  204. package/dist/cli/serverUnavailable.js +0 -1
  205. package/dist/cli/serverUnavailable.js.map +1 -1
  206. package/dist/cli/serverVersion.d.ts +0 -22
  207. package/dist/cli/serverVersion.d.ts.map +1 -1
  208. package/dist/cli/serverVersion.js +0 -12
  209. package/dist/cli/serverVersion.js.map +1 -1
  210. package/dist/cli/telemetry.d.ts +0 -4
  211. package/dist/cli/telemetry.d.ts.map +1 -1
  212. package/dist/cli/telemetry.js +0 -4
  213. package/dist/cli/telemetry.js.map +1 -1
  214. package/dist/config/evaluateFlags.d.ts +0 -4
  215. package/dist/config/evaluateFlags.d.ts.map +1 -1
  216. package/dist/config/evaluateFlags.js +0 -11
  217. package/dist/config/evaluateFlags.js.map +1 -1
  218. package/dist/config/featureFlagUserKey.d.ts +0 -3
  219. package/dist/config/featureFlagUserKey.d.ts.map +1 -1
  220. package/dist/config/featureFlagUserKey.js +0 -3
  221. package/dist/config/featureFlagUserKey.js.map +1 -1
  222. package/dist/config/flags.d.ts +0 -14
  223. package/dist/config/flags.d.ts.map +1 -1
  224. package/dist/config/flags.js +0 -27
  225. package/dist/config/flags.js.map +1 -1
  226. package/dist/config/proxy.d.ts +0 -3
  227. package/dist/config/proxy.d.ts.map +1 -1
  228. package/dist/config/proxy.js +0 -11
  229. package/dist/config/proxy.js.map +1 -1
  230. package/dist/config/telemetry.d.ts +0 -13
  231. package/dist/config/telemetry.d.ts.map +1 -1
  232. package/dist/config/telemetry.js +0 -13
  233. package/dist/config/telemetry.js.map +1 -1
  234. package/dist/config/telemetryContract.d.ts +0 -1
  235. package/dist/config/telemetryContract.d.ts.map +1 -1
  236. package/dist/config/telemetryContract.js +0 -1
  237. package/dist/config/telemetryContract.js.map +1 -1
  238. package/dist/hosts/workerDefaults.d.ts +0 -69
  239. package/dist/hosts/workerDefaults.d.ts.map +1 -1
  240. package/dist/hosts/workerDefaults.js +0 -68
  241. package/dist/hosts/workerDefaults.js.map +1 -1
  242. package/dist/index-core.d.ts.map +1 -1
  243. package/dist/index-core.js +0 -2
  244. package/dist/index-core.js.map +1 -1
  245. package/dist/index.d.ts +0 -20
  246. package/dist/index.d.ts.map +1 -1
  247. package/dist/index.js +2 -105
  248. package/dist/index.js.map +1 -1
  249. package/dist/install/allowlists.d.ts +0 -32
  250. package/dist/install/allowlists.d.ts.map +1 -1
  251. package/dist/install/allowlists.js +0 -44
  252. package/dist/install/allowlists.js.map +1 -1
  253. package/dist/install/automaticCliUpdate.d.ts +0 -6
  254. package/dist/install/automaticCliUpdate.d.ts.map +1 -1
  255. package/dist/install/automaticCliUpdate.js +0 -13
  256. package/dist/install/automaticCliUpdate.js.map +1 -1
  257. package/dist/install/channelCli.d.ts +0 -1
  258. package/dist/install/channelCli.d.ts.map +1 -1
  259. package/dist/install/channelCli.js +0 -3
  260. package/dist/install/channelCli.js.map +1 -1
  261. package/dist/install/channelManager.d.ts +0 -14
  262. package/dist/install/channelManager.d.ts.map +1 -1
  263. package/dist/install/channelManager.js +0 -22
  264. package/dist/install/channelManager.js.map +1 -1
  265. package/dist/install/codexGuidance.d.ts +0 -1
  266. package/dist/install/codexGuidance.d.ts.map +1 -1
  267. package/dist/install/codexGuidance.js +0 -7
  268. package/dist/install/codexGuidance.js.map +1 -1
  269. package/dist/install/globalBootstrap.d.ts +0 -25
  270. package/dist/install/globalBootstrap.d.ts.map +1 -1
  271. package/dist/install/globalBootstrap.js +0 -10
  272. package/dist/install/globalBootstrap.js.map +1 -1
  273. package/dist/install/harnesses.d.ts +0 -66
  274. package/dist/install/harnesses.d.ts.map +1 -1
  275. package/dist/install/harnesses.js +0 -60
  276. package/dist/install/harnesses.js.map +1 -1
  277. package/dist/install/installationChannel.d.ts +0 -1
  278. package/dist/install/installationChannel.d.ts.map +1 -1
  279. package/dist/install/installationChannel.js +0 -1
  280. package/dist/install/installationChannel.js.map +1 -1
  281. package/dist/install/legacyMcp.d.ts +0 -23
  282. package/dist/install/legacyMcp.d.ts.map +1 -1
  283. package/dist/install/legacyMcp.js +3 -46
  284. package/dist/install/legacyMcp.js.map +1 -1
  285. package/dist/install/mcpRegistration.d.ts +0 -41
  286. package/dist/install/mcpRegistration.d.ts.map +1 -1
  287. package/dist/install/mcpRegistration.js +2 -70
  288. package/dist/install/mcpRegistration.js.map +1 -1
  289. package/dist/library/HubClient.d.ts +0 -2
  290. package/dist/library/HubClient.d.ts.map +1 -1
  291. package/dist/library/HubClient.js +0 -4
  292. package/dist/library/HubClient.js.map +1 -1
  293. package/dist/library/HubServer.d.ts +0 -1
  294. package/dist/library/HubServer.d.ts.map +1 -1
  295. package/dist/library/HubServer.js +0 -1
  296. package/dist/library/HubServer.js.map +1 -1
  297. package/dist/library/StaticPreviewServer.d.ts +0 -1
  298. package/dist/library/StaticPreviewServer.d.ts.map +1 -1
  299. package/dist/library/StaticPreviewServer.js +0 -1
  300. package/dist/library/StaticPreviewServer.js.map +1 -1
  301. package/dist/library/http.d.ts +0 -2
  302. package/dist/library/http.d.ts.map +1 -1
  303. package/dist/library/http.js +0 -2
  304. package/dist/library/http.js.map +1 -1
  305. package/dist/library/importFiles.d.ts +0 -6
  306. package/dist/library/importFiles.d.ts.map +1 -1
  307. package/dist/library/importFiles.js +45 -11
  308. package/dist/library/importFiles.js.map +1 -1
  309. package/dist/mcp/changeBatchClassification.d.ts +0 -40
  310. package/dist/mcp/changeBatchClassification.d.ts.map +1 -1
  311. package/dist/mcp/changeBatchClassification.js +0 -34
  312. package/dist/mcp/changeBatchClassification.js.map +1 -1
  313. package/dist/prompts/commentVariationPrompts.d.ts +0 -5
  314. package/dist/prompts/commentVariationPrompts.d.ts.map +1 -1
  315. package/dist/prompts/commentVariationPrompts.js +0 -5
  316. package/dist/prompts/commentVariationPrompts.js.map +1 -1
  317. package/dist/prototype-host.js +0 -15
  318. package/dist/prototype-host.js.map +1 -1
  319. package/dist/proxy-middleware/preview-bridge.d.ts +0 -2
  320. package/dist/proxy-middleware/preview-bridge.d.ts.map +1 -1
  321. package/dist/proxy-middleware/preview-bridge.js +0 -2
  322. package/dist/proxy-middleware/preview-bridge.js.map +1 -1
  323. package/dist/proxy-middleware/preview-connections.d.ts +0 -1
  324. package/dist/proxy-middleware/preview-connections.d.ts.map +1 -1
  325. package/dist/proxy-middleware/preview-connections.js +0 -1
  326. package/dist/proxy-middleware/preview-connections.js.map +1 -1
  327. package/dist/proxy-middleware/proxy-config.d.ts +0 -12
  328. package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
  329. package/dist/proxy-middleware/proxy-config.js +2 -49
  330. package/dist/proxy-middleware/proxy-config.js.map +1 -1
  331. package/dist/routes/account.d.ts +0 -1
  332. package/dist/routes/account.d.ts.map +1 -1
  333. package/dist/routes/account.js +0 -2
  334. package/dist/routes/account.js.map +1 -1
  335. package/dist/routes/agentVariants.d.ts +0 -15
  336. package/dist/routes/agentVariants.d.ts.map +1 -1
  337. package/dist/routes/agentVariants.js +6 -320
  338. package/dist/routes/agentVariants.js.map +1 -1
  339. package/dist/routes/cli.d.ts +0 -17
  340. package/dist/routes/cli.d.ts.map +1 -1
  341. package/dist/routes/cli.js +0 -13
  342. package/dist/routes/cli.js.map +1 -1
  343. package/dist/routes/emptyStatePage.d.ts +0 -12
  344. package/dist/routes/emptyStatePage.d.ts.map +1 -1
  345. package/dist/routes/emptyStatePage.js +0 -12
  346. package/dist/routes/emptyStatePage.js.map +1 -1
  347. package/dist/routes/git.d.ts.map +1 -1
  348. package/dist/routes/git.js +0 -13
  349. package/dist/routes/git.js.map +1 -1
  350. package/dist/routes/inlineStartTracker.d.ts +0 -16
  351. package/dist/routes/inlineStartTracker.d.ts.map +1 -1
  352. package/dist/routes/inlineStartTracker.js.map +1 -1
  353. package/dist/routes/integrations.d.ts +0 -6
  354. package/dist/routes/integrations.d.ts.map +1 -1
  355. package/dist/routes/integrations.js +0 -6
  356. package/dist/routes/integrations.js.map +1 -1
  357. package/dist/routes/library/app.d.ts +0 -1
  358. package/dist/routes/library/app.d.ts.map +1 -1
  359. package/dist/routes/library/app.js +0 -1
  360. package/dist/routes/library/app.js.map +1 -1
  361. package/dist/routes/library/index.d.ts +0 -1
  362. package/dist/routes/library/index.d.ts.map +1 -1
  363. package/dist/routes/library/index.js +0 -1
  364. package/dist/routes/library/index.js.map +1 -1
  365. package/dist/routes/library/middleware.d.ts +0 -3
  366. package/dist/routes/library/middleware.d.ts.map +1 -1
  367. package/dist/routes/library/middleware.js +0 -4
  368. package/dist/routes/library/middleware.js.map +1 -1
  369. package/dist/routes/library/navigation.d.ts +0 -1
  370. package/dist/routes/library/navigation.d.ts.map +1 -1
  371. package/dist/routes/library/navigation.js +0 -1
  372. package/dist/routes/library/navigation.js.map +1 -1
  373. package/dist/routes/library/projects.d.ts +0 -1
  374. package/dist/routes/library/projects.d.ts.map +1 -1
  375. package/dist/routes/library/projects.js +0 -1
  376. package/dist/routes/library/projects.js.map +1 -1
  377. package/dist/routes/library/staticPreview.d.ts +0 -1
  378. package/dist/routes/library/staticPreview.d.ts.map +1 -1
  379. package/dist/routes/library/staticPreview.js +0 -1
  380. package/dist/routes/library/staticPreview.js.map +1 -1
  381. package/dist/routes/library/variants.d.ts +0 -1
  382. package/dist/routes/library/variants.d.ts.map +1 -1
  383. package/dist/routes/library/variants.js +0 -1
  384. package/dist/routes/library/variants.js.map +1 -1
  385. package/dist/routes/mcp.d.ts +0 -3
  386. package/dist/routes/mcp.d.ts.map +1 -1
  387. package/dist/routes/mcp.js +0 -5
  388. package/dist/routes/mcp.js.map +1 -1
  389. package/dist/routes/prototypeHost.d.ts +0 -2
  390. package/dist/routes/prototypeHost.d.ts.map +1 -1
  391. package/dist/routes/prototypeHost.js +6 -32
  392. package/dist/routes/prototypeHost.js.map +1 -1
  393. package/dist/routes/static.d.ts +0 -3
  394. package/dist/routes/static.d.ts.map +1 -1
  395. package/dist/routes/static.js +0 -6
  396. package/dist/routes/static.js.map +1 -1
  397. package/dist/routes/support.d.ts +0 -3
  398. package/dist/routes/support.d.ts.map +1 -1
  399. package/dist/routes/support.js +0 -3
  400. package/dist/routes/support.js.map +1 -1
  401. package/dist/server.d.ts +0 -42
  402. package/dist/server.d.ts.map +1 -1
  403. package/dist/server.js +1 -129
  404. package/dist/server.js.map +1 -1
  405. package/dist/services/AuthService.d.ts +0 -76
  406. package/dist/services/AuthService.d.ts.map +1 -1
  407. package/dist/services/AuthService.js +0 -112
  408. package/dist/services/AuthService.js.map +1 -1
  409. package/dist/services/BrowserAgentClient.d.ts +1 -21
  410. package/dist/services/BrowserAgentClient.d.ts.map +1 -1
  411. package/dist/services/BrowserAgentClient.js +0 -10
  412. package/dist/services/BrowserAgentClient.js.map +1 -1
  413. package/dist/services/BundleStore.d.ts +0 -18
  414. package/dist/services/BundleStore.d.ts.map +1 -1
  415. package/dist/services/BundleStore.js +0 -10
  416. package/dist/services/BundleStore.js.map +1 -1
  417. package/dist/services/CliLogForwarder.d.ts +0 -26
  418. package/dist/services/CliLogForwarder.d.ts.map +1 -1
  419. package/dist/services/CliLogForwarder.js +1 -33
  420. package/dist/services/CliLogForwarder.js.map +1 -1
  421. package/dist/services/CommitMessageGenerator.d.ts +0 -6
  422. package/dist/services/CommitMessageGenerator.d.ts.map +1 -1
  423. package/dist/services/CommitMessageGenerator.js +0 -3
  424. package/dist/services/CommitMessageGenerator.js.map +1 -1
  425. package/dist/services/ComponentSearchService.d.ts +2 -16
  426. package/dist/services/ComponentSearchService.d.ts.map +1 -1
  427. package/dist/services/ComponentSearchService.js +2 -56
  428. package/dist/services/ComponentSearchService.js.map +1 -1
  429. package/dist/services/ConfigManager.d.ts +0 -113
  430. package/dist/services/ConfigManager.d.ts.map +1 -1
  431. package/dist/services/ConfigManager.js +0 -101
  432. package/dist/services/ConfigManager.js.map +1 -1
  433. package/dist/services/DependencyPreparationService.d.ts +0 -6
  434. package/dist/services/DependencyPreparationService.d.ts.map +1 -1
  435. package/dist/services/DependencyPreparationService.js +0 -22
  436. package/dist/services/DependencyPreparationService.js.map +1 -1
  437. package/dist/services/DevServerRuntimeService.d.ts +0 -20
  438. package/dist/services/DevServerRuntimeService.d.ts.map +1 -1
  439. package/dist/services/DevServerRuntimeService.js +0 -46
  440. package/dist/services/DevServerRuntimeService.js.map +1 -1
  441. package/dist/services/FeatureFlagService.d.ts +0 -15
  442. package/dist/services/FeatureFlagService.d.ts.map +1 -1
  443. package/dist/services/FeatureFlagService.js +0 -23
  444. package/dist/services/FeatureFlagService.js.map +1 -1
  445. package/dist/services/GatewayClient.d.ts +0 -27
  446. package/dist/services/GatewayClient.d.ts.map +1 -1
  447. package/dist/services/GatewayClient.js +0 -25
  448. package/dist/services/GatewayClient.js.map +1 -1
  449. package/dist/services/HistoryReplayService.d.ts +0 -31
  450. package/dist/services/HistoryReplayService.d.ts.map +1 -1
  451. package/dist/services/HistoryReplayService.js +2 -55
  452. package/dist/services/HistoryReplayService.js.map +1 -1
  453. package/dist/services/HubDiscovery.d.ts +0 -8
  454. package/dist/services/HubDiscovery.d.ts.map +1 -1
  455. package/dist/services/HubDiscovery.js +0 -8
  456. package/dist/services/HubDiscovery.js.map +1 -1
  457. package/dist/services/HubNavigation.d.ts +0 -6
  458. package/dist/services/HubNavigation.d.ts.map +1 -1
  459. package/dist/services/HubNavigation.js +5 -8
  460. package/dist/services/HubNavigation.js.map +1 -1
  461. package/dist/services/IntegrationsClient.d.ts +0 -34
  462. package/dist/services/IntegrationsClient.d.ts.map +1 -1
  463. package/dist/services/IntegrationsClient.js +0 -27
  464. package/dist/services/IntegrationsClient.js.map +1 -1
  465. package/dist/services/LocalGitService.d.ts +0 -57
  466. package/dist/services/LocalGitService.d.ts.map +1 -1
  467. package/dist/services/LocalGitService.js +4 -85
  468. package/dist/services/LocalGitService.js.map +1 -1
  469. package/dist/services/MCPOnboardingTelemetry.d.ts +0 -9
  470. package/dist/services/MCPOnboardingTelemetry.d.ts.map +1 -1
  471. package/dist/services/MCPOnboardingTelemetry.js +0 -9
  472. package/dist/services/MCPOnboardingTelemetry.js.map +1 -1
  473. package/dist/services/MCPVariantsTelemetry.d.ts +0 -2
  474. package/dist/services/MCPVariantsTelemetry.d.ts.map +1 -1
  475. package/dist/services/MCPVariantsTelemetry.js +0 -2
  476. package/dist/services/MCPVariantsTelemetry.js.map +1 -1
  477. package/dist/services/OperatingSystemServices.d.ts +0 -12
  478. package/dist/services/OperatingSystemServices.d.ts.map +1 -1
  479. package/dist/services/OperatingSystemServices.js +0 -7
  480. package/dist/services/OperatingSystemServices.js.map +1 -1
  481. package/dist/services/PRTitleGenerator.d.ts +0 -7
  482. package/dist/services/PRTitleGenerator.d.ts.map +1 -1
  483. package/dist/services/PRTitleGenerator.js +0 -3
  484. package/dist/services/PRTitleGenerator.js.map +1 -1
  485. package/dist/services/ProjectCardPreviews.d.ts +0 -5
  486. package/dist/services/ProjectCardPreviews.d.ts.map +1 -1
  487. package/dist/services/ProjectCardPreviews.js +0 -5
  488. package/dist/services/ProjectCardPreviews.js.map +1 -1
  489. package/dist/services/ProjectDetectionService.d.ts +0 -4
  490. package/dist/services/ProjectDetectionService.d.ts.map +1 -1
  491. package/dist/services/ProjectDetectionService.js +2 -44
  492. package/dist/services/ProjectDetectionService.js.map +1 -1
  493. package/dist/services/ProjectFolderPicker.d.ts +0 -3
  494. package/dist/services/ProjectFolderPicker.d.ts.map +1 -1
  495. package/dist/services/ProjectFolderPicker.js +0 -4
  496. package/dist/services/ProjectFolderPicker.js.map +1 -1
  497. package/dist/services/ProjectImport.d.ts +0 -1
  498. package/dist/services/ProjectImport.d.ts.map +1 -1
  499. package/dist/services/ProjectImport.js +0 -3
  500. package/dist/services/ProjectImport.js.map +1 -1
  501. package/dist/services/ProjectLibrary.d.ts +0 -18
  502. package/dist/services/ProjectLibrary.d.ts.map +1 -1
  503. package/dist/services/ProjectLibrary.js +0 -20
  504. package/dist/services/ProjectLibrary.js.map +1 -1
  505. package/dist/services/ProjectMetadataStore.d.ts +0 -73
  506. package/dist/services/ProjectMetadataStore.d.ts.map +1 -1
  507. package/dist/services/ProjectMetadataStore.js +0 -90
  508. package/dist/services/ProjectMetadataStore.js.map +1 -1
  509. package/dist/services/ProjectPackageManager.d.ts +0 -12
  510. package/dist/services/ProjectPackageManager.d.ts.map +1 -1
  511. package/dist/services/ProjectPackageManager.js +0 -16
  512. package/dist/services/ProjectPackageManager.js.map +1 -1
  513. package/dist/services/ProjectRegistry.d.ts +0 -16
  514. package/dist/services/ProjectRegistry.d.ts.map +1 -1
  515. package/dist/services/ProjectRegistry.js +0 -18
  516. package/dist/services/ProjectRegistry.js.map +1 -1
  517. package/dist/services/ProjectRuntimeService.d.ts +0 -4
  518. package/dist/services/ProjectRuntimeService.d.ts.map +1 -1
  519. package/dist/services/ProjectRuntimeService.js +0 -5
  520. package/dist/services/ProjectRuntimeService.js.map +1 -1
  521. package/dist/services/ProjectScreenshotService.d.ts +0 -5
  522. package/dist/services/ProjectScreenshotService.d.ts.map +1 -1
  523. package/dist/services/ProjectScreenshotService.js +0 -6
  524. package/dist/services/ProjectScreenshotService.js.map +1 -1
  525. package/dist/services/ProjectStorage.d.ts +0 -4
  526. package/dist/services/ProjectStorage.d.ts.map +1 -1
  527. package/dist/services/ProjectStorage.js +0 -4
  528. package/dist/services/ProjectStorage.js.map +1 -1
  529. package/dist/services/PrototypeBuildService.d.ts +1 -23
  530. package/dist/services/PrototypeBuildService.d.ts.map +1 -1
  531. package/dist/services/PrototypeBuildService.js +6 -31
  532. package/dist/services/PrototypeBuildService.js.map +1 -1
  533. package/dist/services/PrototypeDeployService.d.ts +0 -20
  534. package/dist/services/PrototypeDeployService.d.ts.map +1 -1
  535. package/dist/services/PrototypeDeployService.js +1 -24
  536. package/dist/services/PrototypeDeployService.js.map +1 -1
  537. package/dist/services/RequestAuthContext.d.ts +0 -5
  538. package/dist/services/RequestAuthContext.d.ts.map +1 -1
  539. package/dist/services/RequestAuthContext.js +0 -5
  540. package/dist/services/RequestAuthContext.js.map +1 -1
  541. package/dist/services/SessionBridgeService.d.ts.map +1 -1
  542. package/dist/services/SessionBridgeService.js +0 -2
  543. package/dist/services/SessionBridgeService.js.map +1 -1
  544. package/dist/services/SessionService.d.ts +0 -4
  545. package/dist/services/SessionService.d.ts.map +1 -1
  546. package/dist/services/SessionService.js +1 -22
  547. package/dist/services/SessionService.js.map +1 -1
  548. package/dist/services/StaticFileService.d.ts +0 -9
  549. package/dist/services/StaticFileService.d.ts.map +1 -1
  550. package/dist/services/StaticFileService.js +0 -11
  551. package/dist/services/StaticFileService.js.map +1 -1
  552. package/dist/services/StaticLibraryPreviews.d.ts +0 -3
  553. package/dist/services/StaticLibraryPreviews.d.ts.map +1 -1
  554. package/dist/services/StaticLibraryPreviews.js +0 -3
  555. package/dist/services/StaticLibraryPreviews.js.map +1 -1
  556. package/dist/services/StaticPreviewServer.d.ts +0 -16
  557. package/dist/services/StaticPreviewServer.d.ts.map +1 -1
  558. package/dist/services/StaticPreviewServer.js +2 -28
  559. package/dist/services/StaticPreviewServer.js.map +1 -1
  560. package/dist/services/SupabaseAuthService.d.ts +0 -11
  561. package/dist/services/SupabaseAuthService.d.ts.map +1 -1
  562. package/dist/services/SupabaseAuthService.js +0 -11
  563. package/dist/services/SupabaseAuthService.js.map +1 -1
  564. package/dist/services/SupportTicketService.d.ts +0 -4
  565. package/dist/services/SupportTicketService.d.ts.map +1 -1
  566. package/dist/services/SupportTicketService.js +0 -4
  567. package/dist/services/SupportTicketService.js.map +1 -1
  568. package/dist/services/TelemetryService.d.ts +0 -182
  569. package/dist/services/TelemetryService.d.ts.map +1 -1
  570. package/dist/services/TelemetryService.js +0 -193
  571. package/dist/services/TelemetryService.js.map +1 -1
  572. package/dist/services/TreeStore.d.ts +0 -72
  573. package/dist/services/TreeStore.d.ts.map +1 -1
  574. package/dist/services/TreeStore.js +0 -93
  575. package/dist/services/TreeStore.js.map +1 -1
  576. package/dist/services/VariantGenerationService.d.ts +0 -32
  577. package/dist/services/VariantGenerationService.d.ts.map +1 -1
  578. package/dist/services/VariantGenerationService.js +5 -62
  579. package/dist/services/VariantGenerationService.js.map +1 -1
  580. package/dist/services/VariantHistoryService.d.ts +0 -114
  581. package/dist/services/VariantHistoryService.d.ts.map +1 -1
  582. package/dist/services/VariantHistoryService.js +2 -144
  583. package/dist/services/VariantHistoryService.js.map +1 -1
  584. package/dist/services/VariantRunService.d.ts +0 -31
  585. package/dist/services/VariantRunService.d.ts.map +1 -1
  586. package/dist/services/VariantRunService.js +0 -35
  587. package/dist/services/VariantRunService.js.map +1 -1
  588. package/dist/services/VariantsRuntime.d.ts +0 -3
  589. package/dist/services/VariantsRuntime.d.ts.map +1 -1
  590. package/dist/services/VariantsRuntime.js +0 -5
  591. package/dist/services/VariantsRuntime.js.map +1 -1
  592. package/dist/services/WorktreeManager.d.ts +0 -217
  593. package/dist/services/WorktreeManager.d.ts.map +1 -1
  594. package/dist/services/WorktreeManager.js +3 -321
  595. package/dist/services/WorktreeManager.js.map +1 -1
  596. package/dist/services/accessTokenRefresh.d.ts +0 -25
  597. package/dist/services/accessTokenRefresh.d.ts.map +1 -1
  598. package/dist/services/accessTokenRefresh.js +0 -25
  599. package/dist/services/accessTokenRefresh.js.map +1 -1
  600. package/dist/services/adapters/TailwindTokenAdapter.d.ts +0 -29
  601. package/dist/services/adapters/TailwindTokenAdapter.d.ts.map +1 -1
  602. package/dist/services/adapters/TailwindTokenAdapter.js +1 -46
  603. package/dist/services/adapters/TailwindTokenAdapter.js.map +1 -1
  604. package/dist/services/createAgentVariantsOrchestrator.d.ts +0 -18
  605. package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
  606. package/dist/services/createAgentVariantsOrchestrator.js +0 -22
  607. package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
  608. package/dist/services/extractors/CSSVariableExtractor.d.ts +0 -25
  609. package/dist/services/extractors/CSSVariableExtractor.d.ts.map +1 -1
  610. package/dist/services/extractors/CSSVariableExtractor.js +1 -42
  611. package/dist/services/extractors/CSSVariableExtractor.js.map +1 -1
  612. package/dist/services/historyRoots.d.ts +0 -12
  613. package/dist/services/historyRoots.d.ts.map +1 -1
  614. package/dist/services/historyRoots.js +0 -13
  615. package/dist/services/historyRoots.js.map +1 -1
  616. package/dist/services/libraryErrors.d.ts +0 -1
  617. package/dist/services/libraryErrors.d.ts.map +1 -1
  618. package/dist/services/libraryErrors.js +0 -1
  619. package/dist/services/libraryErrors.js.map +1 -1
  620. package/dist/services/pendingLogin.d.ts +0 -13
  621. package/dist/services/pendingLogin.d.ts.map +1 -1
  622. package/dist/services/pendingLogin.js +0 -3
  623. package/dist/services/pendingLogin.js.map +1 -1
  624. package/dist/services/staticProjectTarget.d.ts +0 -4
  625. package/dist/services/staticProjectTarget.d.ts.map +1 -1
  626. package/dist/services/staticProjectTarget.js +0 -4
  627. package/dist/services/staticProjectTarget.js.map +1 -1
  628. package/dist/services/staticStarter.d.ts +0 -20
  629. package/dist/services/staticStarter.d.ts.map +1 -1
  630. package/dist/services/staticStarter.js +0 -20
  631. package/dist/services/staticStarter.js.map +1 -1
  632. package/dist/services/templates/designCatalog.d.ts +0 -11
  633. package/dist/services/templates/designCatalog.d.ts.map +1 -1
  634. package/dist/services/templates/designCatalog.js +0 -26
  635. package/dist/services/templates/designCatalog.js.map +1 -1
  636. package/dist/services/templates/viteReactTs.d.ts +0 -26
  637. package/dist/services/templates/viteReactTs.d.ts.map +1 -1
  638. package/dist/services/templates/viteReactTs.js +0 -20
  639. package/dist/services/templates/viteReactTs.js.map +1 -1
  640. package/dist/storage/library/BundleMetadataStore.d.ts +0 -16
  641. package/dist/storage/library/BundleMetadataStore.d.ts.map +1 -1
  642. package/dist/storage/library/BundleMetadataStore.js +0 -17
  643. package/dist/storage/library/BundleMetadataStore.js.map +1 -1
  644. package/dist/storage/library/CoordinatorRecords.d.ts +0 -9
  645. package/dist/storage/library/CoordinatorRecords.d.ts.map +1 -1
  646. package/dist/storage/library/CoordinatorRecords.js +0 -9
  647. package/dist/storage/library/CoordinatorRecords.js.map +1 -1
  648. package/dist/storage/library/ProjectPreviewCache.d.ts +0 -4
  649. package/dist/storage/library/ProjectPreviewCache.d.ts.map +1 -1
  650. package/dist/storage/library/ProjectPreviewCache.js +0 -4
  651. package/dist/storage/library/ProjectPreviewCache.js.map +1 -1
  652. package/dist/storage/library/ProjectRecords.d.ts +0 -17
  653. package/dist/storage/library/ProjectRecords.d.ts.map +1 -1
  654. package/dist/storage/library/ProjectRecords.js +0 -17
  655. package/dist/storage/library/ProjectRecords.js.map +1 -1
  656. package/dist/storage/library/database.d.ts +0 -3
  657. package/dist/storage/library/database.d.ts.map +1 -1
  658. package/dist/storage/library/database.js +0 -3
  659. package/dist/storage/library/database.js.map +1 -1
  660. package/dist/storage/library/migrations.d.ts +0 -2
  661. package/dist/storage/library/migrations.d.ts.map +1 -1
  662. package/dist/storage/library/migrations.js +0 -2
  663. package/dist/storage/library/migrations.js.map +1 -1
  664. package/dist/storage/library/sourcePresentation.d.ts +0 -1
  665. package/dist/storage/library/sourcePresentation.d.ts.map +1 -1
  666. package/dist/storage/library/sourcePresentation.js +0 -1
  667. package/dist/storage/library/sourcePresentation.js.map +1 -1
  668. package/dist/storage/project-metadata/ProjectMetadataRecords.d.ts +0 -11
  669. package/dist/storage/project-metadata/ProjectMetadataRecords.d.ts.map +1 -1
  670. package/dist/storage/project-metadata/ProjectMetadataRecords.js +0 -13
  671. package/dist/storage/project-metadata/ProjectMetadataRecords.js.map +1 -1
  672. package/dist/storage/project-metadata/database.d.ts +0 -1
  673. package/dist/storage/project-metadata/database.d.ts.map +1 -1
  674. package/dist/storage/project-metadata/database.js +0 -7
  675. package/dist/storage/project-metadata/database.js.map +1 -1
  676. package/dist/storage/project-metadata/migrations.d.ts +0 -42
  677. package/dist/storage/project-metadata/migrations.d.ts.map +1 -1
  678. package/dist/storage/project-metadata/migrations.js +0 -41
  679. package/dist/storage/project-metadata/migrations.js.map +1 -1
  680. package/dist/types/account.d.ts +0 -1
  681. package/dist/types/account.d.ts.map +1 -1
  682. package/dist/types/change-request-types.d.ts +0 -167
  683. package/dist/types/change-request-types.d.ts.map +1 -1
  684. package/dist/types/change-types.d.ts +0 -1
  685. package/dist/types/change-types.d.ts.map +1 -1
  686. package/dist/types/change-types.js +0 -1
  687. package/dist/types/change-types.js.map +1 -1
  688. package/dist/types/project-library.d.ts +0 -1
  689. package/dist/types/project-library.d.ts.map +1 -1
  690. package/dist/types/style-manipulation-types.d.ts +0 -69
  691. package/dist/types/style-manipulation-types.d.ts.map +1 -1
  692. package/dist/types/style-manipulation-types.js +0 -26
  693. package/dist/types/style-manipulation-types.js.map +1 -1
  694. package/dist/types/token-types.d.ts +0 -30
  695. package/dist/types/token-types.d.ts.map +1 -1
  696. package/dist/types/token-types.js +0 -1
  697. package/dist/types/token-types.js.map +1 -1
  698. package/dist/types/variant-history.d.ts +0 -39
  699. package/dist/types/variant-history.d.ts.map +1 -1
  700. package/dist/utils/branchNames.d.ts +0 -1
  701. package/dist/utils/branchNames.d.ts.map +1 -1
  702. package/dist/utils/branchNames.js +0 -2
  703. package/dist/utils/branchNames.js.map +1 -1
  704. package/dist/utils/cloneOrCopyDirSync.d.ts +0 -12
  705. package/dist/utils/cloneOrCopyDirSync.d.ts.map +1 -1
  706. package/dist/utils/cloneOrCopyDirSync.js +0 -16
  707. package/dist/utils/cloneOrCopyDirSync.js.map +1 -1
  708. package/dist/utils/devServerCommand.d.ts +0 -23
  709. package/dist/utils/devServerCommand.d.ts.map +1 -1
  710. package/dist/utils/devServerCommand.js +0 -24
  711. package/dist/utils/devServerCommand.js.map +1 -1
  712. package/dist/utils/devServerError.d.ts +0 -16
  713. package/dist/utils/devServerError.d.ts.map +1 -1
  714. package/dist/utils/devServerError.js +0 -17
  715. package/dist/utils/devServerError.js.map +1 -1
  716. package/dist/utils/displayLocale.d.ts +0 -2
  717. package/dist/utils/displayLocale.d.ts.map +1 -1
  718. package/dist/utils/displayLocale.js +0 -2
  719. package/dist/utils/displayLocale.js.map +1 -1
  720. package/dist/utils/elementFileHintSignals.d.ts +0 -5
  721. package/dist/utils/elementFileHintSignals.d.ts.map +1 -1
  722. package/dist/utils/elementFileHintSignals.js +0 -5
  723. package/dist/utils/elementFileHintSignals.js.map +1 -1
  724. package/dist/utils/formatElementTargetingContext.d.ts +0 -6
  725. package/dist/utils/formatElementTargetingContext.d.ts.map +1 -1
  726. package/dist/utils/formatElementTargetingContext.js +3 -9
  727. package/dist/utils/formatElementTargetingContext.js.map +1 -1
  728. package/dist/utils/hostAgentEnv.d.ts +0 -17
  729. package/dist/utils/hostAgentEnv.d.ts.map +1 -1
  730. package/dist/utils/hostAgentEnv.js +0 -17
  731. package/dist/utils/hostAgentEnv.js.map +1 -1
  732. package/dist/utils/htmlDocument.d.ts +0 -5
  733. package/dist/utils/htmlDocument.d.ts.map +1 -1
  734. package/dist/utils/htmlDocument.js +2 -7
  735. package/dist/utils/htmlDocument.js.map +1 -1
  736. package/dist/utils/internalGitIdentity.d.ts +0 -5
  737. package/dist/utils/internalGitIdentity.d.ts.map +1 -1
  738. package/dist/utils/internalGitIdentity.js +0 -5
  739. package/dist/utils/internalGitIdentity.js.map +1 -1
  740. package/dist/utils/logger.d.ts +0 -5
  741. package/dist/utils/logger.d.ts.map +1 -1
  742. package/dist/utils/logger.js +2 -19
  743. package/dist/utils/logger.js.map +1 -1
  744. package/dist/utils/loginShellPath.d.ts +0 -9
  745. package/dist/utils/loginShellPath.d.ts.map +1 -1
  746. package/dist/utils/loginShellPath.js +0 -69
  747. package/dist/utils/loginShellPath.js.map +1 -1
  748. package/dist/utils/loopback.d.ts +0 -1
  749. package/dist/utils/loopback.d.ts.map +1 -1
  750. package/dist/utils/loopback.js +0 -1
  751. package/dist/utils/loopback.js.map +1 -1
  752. package/dist/utils/pid.d.ts +0 -1
  753. package/dist/utils/pid.d.ts.map +1 -1
  754. package/dist/utils/pid.js +0 -1
  755. package/dist/utils/pid.js.map +1 -1
  756. package/dist/utils/portUtils.d.ts +0 -15
  757. package/dist/utils/portUtils.d.ts.map +1 -1
  758. package/dist/utils/portUtils.js +0 -21
  759. package/dist/utils/portUtils.js.map +1 -1
  760. package/dist/utils/queueAccess.d.ts +0 -9
  761. package/dist/utils/queueAccess.d.ts.map +1 -1
  762. package/dist/utils/queueAccess.js +0 -9
  763. package/dist/utils/queueAccess.js.map +1 -1
  764. package/dist/utils/skillWriter.d.ts +0 -17
  765. package/dist/utils/skillWriter.d.ts.map +1 -1
  766. package/dist/utils/skillWriter.js +0 -20
  767. package/dist/utils/skillWriter.js.map +1 -1
  768. package/dist/utils/skills/claude-skill.d.ts +0 -5
  769. package/dist/utils/skills/claude-skill.d.ts.map +1 -1
  770. package/dist/utils/skills/claude-skill.js +0 -5
  771. package/dist/utils/skills/claude-skill.js.map +1 -1
  772. package/dist/utils/skills/cli-guidance.d.ts +0 -8
  773. package/dist/utils/skills/cli-guidance.d.ts.map +1 -1
  774. package/dist/utils/skills/cli-guidance.js +0 -8
  775. package/dist/utils/skills/cli-guidance.js.map +1 -1
  776. package/dist/utils/skills/cursor-rules.d.ts +0 -6
  777. package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
  778. package/dist/utils/skills/cursor-rules.js +0 -6
  779. package/dist/utils/skills/cursor-rules.js.map +1 -1
  780. package/dist/utils/variantPreviewPort.d.ts +0 -3
  781. package/dist/utils/variantPreviewPort.d.ts.map +1 -1
  782. package/dist/utils/variantPreviewPort.js +0 -3
  783. package/dist/utils/variantPreviewPort.js.map +1 -1
  784. package/dist/utils/windowPlacement.d.ts +0 -4
  785. package/dist/utils/windowPlacement.d.ts.map +1 -1
  786. package/dist/utils/windowPlacement.js +0 -4
  787. package/dist/utils/windowPlacement.js.map +1 -1
  788. package/package.json +12 -13
  789. package/scripts/verify-node-version.cjs +0 -3
  790. package/src/ui/dist/assets/{LibraryApp-qbLqcNxM.js → LibraryApp-x6PbzlGr.js} +1 -1
  791. package/src/ui/dist/assets/{main-touv07Dk.js → main-BW1Odsqp.js} +75 -75
  792. package/src/ui/dist/assets/main-DDQRZm89.css +1 -0
  793. package/src/ui/dist/index.html +2 -2
  794. package/dist/utils/skills/describe-motion-protocol.d.ts +0 -10
  795. package/dist/utils/skills/describe-motion-protocol.d.ts.map +0 -1
  796. package/dist/utils/skills/describe-motion-protocol.js +0 -231
  797. package/dist/utils/skills/describe-motion-protocol.js.map +0 -1
  798. package/src/ui/dist/assets/main-BUZjlAHd.css +0 -1
@@ -75,44 +75,14 @@ const FALLBACK_DIRECTION_FOCI = [
75
75
  'Explore tactile depth, layering, and purposeful interaction cues.',
76
76
  'Reduce the concept to its most essential typography and geometry.',
77
77
  ];
78
- // Upper bound on waiting for in-flight history persists during session
79
- // teardown. Generous enough for a full-repo snapshot on a large project;
80
- // small enough that a wedged git subprocess (which has its own 120s block
81
- // timeout) can't make commit/cancel appear hung.
82
78
  const SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS = 20_000;
83
- // Sentinel port for deriving a persist-time serve recipe when the dev server
84
- // hasn't booted yet: resolved into the command, then reverse-substituted to
85
- // the ${PORT} placeholder. Digit-boundary-guarded substitution means only an
86
- // exact standalone occurrence is replaced, and 65535 never appears in any
87
- // framework's default invocation.
88
79
  const RECIPE_PORT_SENTINEL = 65535;
89
- // Fresh worktrees run the Vite React template, whose dev server defaults to
90
- // 5173. Used as the scan start when allocating a fresh variant's preview port.
91
80
  const FRESH_DEV_SERVER_DEFAULT_PORT = 5173;
92
- // Startup attempts for a variant's dev server. Attempt 2 covers a transient
93
- // early exit (with a dependency install first when the output shows
94
- // module-resolution errors); attempt 3 leaves room for one more port step
95
- // when a collision persists. Early exits fail fast, so extra attempts cost
96
- // little wall clock.
97
81
  const DEV_SERVER_START_MAX_ATTEMPTS = 3;
98
- // Auto-restarts allowed after a READY dev server crashes (see the exit
99
- // handler in startVariantDevServer). Two rescues cover transient crashes;
100
- // a third crash means the build is genuinely broken, so stop looping.
101
82
  const DEV_SERVER_MAX_AUTO_RESTARTS = 2;
102
- // Grace before an auto-restart so a crashing process's port and file locks
103
- // are actually released first.
104
83
  const DEV_SERVER_RESTART_DELAY_MS = 1_000;
105
84
  const DESIGN_CONTEXT_ROUTE_SEGMENT = 'design-md';
106
85
  const DESIGN_CONTEXT_VIEW_SEGMENT = 'view';
107
- // Hard ceiling on worktree provisioning so a slow/large host project can never
108
- // stall the `start_variants` / `approve_variant_briefs` tool call indefinitely.
109
- // Existing-project provisioning clones the host working tree once per variant
110
- // (`git worktree add` + untracked-file copy), so its cost scales with repo
111
- // size — a big monorepo (or a React Native tree with native build dirs) used to
112
- // hang the call for 15+ minutes with no signal. With this bound the call fails
113
- // fast and legibly instead. Per-git-op hangs are already caught by simple-git's
114
- // block timeout in WorktreeManager; this is the cross-op backstop. Override via
115
- // env for unusually large repos.
116
86
  const DEFAULT_PROVISION_TIMEOUT_MS = 540_000;
117
87
  const PROVISION_TIMEOUT_MS = (() => {
118
88
  const raw = process.env.RIVET_VARIANTS_PROVISION_TIMEOUT_MS;
@@ -121,10 +91,6 @@ const PROVISION_TIMEOUT_MS = (() => {
121
91
  ? parsed
122
92
  : DEFAULT_PROVISION_TIMEOUT_MS;
123
93
  })();
124
- // Active variant dev servers are useful only while the Rivet app is being used.
125
- // Reclaim them after app/API silence so abandoned sessions do not pin one child
126
- // process per succeeded variant forever. The session state and worktrees stay
127
- // intact; only live preview ports are cleared.
128
94
  const DEFAULT_ACTIVE_VARIANT_SERVER_IDLE_TTL_MS = 30 * 60 * 1000;
129
95
  const ACTIVE_VARIANT_SERVER_IDLE_TTL_MS = (() => {
130
96
  const raw = process.env.RIVET_ACTIVE_VARIANT_SERVER_IDLE_TTL_MS;
@@ -133,7 +99,6 @@ const ACTIVE_VARIANT_SERVER_IDLE_TTL_MS = (() => {
133
99
  ? parsed
134
100
  : DEFAULT_ACTIVE_VARIANT_SERVER_IDLE_TTL_MS;
135
101
  })();
136
- /** Sentinel so callers can distinguish a provisioning timeout from other errors. */
137
102
  class ProvisionTimeoutError extends Error {
138
103
  timeoutMs;
139
104
  constructor(timeoutMs) {
@@ -142,12 +107,6 @@ class ProvisionTimeoutError extends Error {
142
107
  this.name = 'ProvisionTimeoutError';
143
108
  }
144
109
  }
145
- /**
146
- * Reject with `ProvisionTimeoutError` if `work` hasn't settled within
147
- * `timeoutMs`. The underlying work is NOT cancellable (git/fs I/O), so it may
148
- * keep running after we reject — callers should best-effort clean up partial
149
- * state. The timer is unref'd so it never keeps the process alive on its own.
150
- */
151
110
  function withProvisionTimeout(work, timeoutMs) {
152
111
  let timer;
153
112
  const timeout = new Promise((_, reject) => {
@@ -157,11 +116,6 @@ function withProvisionTimeout(work, timeoutMs) {
157
116
  });
158
117
  return Promise.race([work, timeout]).finally(() => clearTimeout(timer));
159
118
  }
160
- /**
161
- * File types an agent-authored asset plan may copy into a generated preview.
162
- * This allowlist protects an agent-controlled path; caller-selected context
163
- * assets use the separate, type-neutral delivery path.
164
- */
165
119
  const ALLOWED_INERT_ASSET_EXTENSIONS = new Set([
166
120
  '.glb',
167
121
  '.gltf',
@@ -191,13 +145,6 @@ const ALLOWED_INERT_ASSET_EXTENSIONS = new Set([
191
145
  '.eot',
192
146
  '.pdf',
193
147
  ]);
194
- /**
195
- * Reject paths that traverse through a "sensitive" directory anywhere
196
- * in their ancestry — `.ssh`, `.aws`, `.config`, `.gnupg`, etc. Even if
197
- * a copy passes the extension allowlist, an agent-controlled source
198
- * resolving inside `~/.ssh/` is almost certainly an exfiltration
199
- * attempt rather than a legitimate asset reference.
200
- */
201
148
  const SENSITIVE_PATH_SEGMENTS = new Set([
202
149
  '.ssh',
203
150
  '.aws',
@@ -214,14 +161,9 @@ const SENSITIVE_PATH_SEGMENTS = new Set([
214
161
  'credentials',
215
162
  ]);
216
163
  function hasSensitivePathSegment(absolutePath) {
217
- // Split on any path separator; check each segment case-insensitively.
218
164
  const segments = absolutePath.split(/[/\\]/).filter(Boolean);
219
165
  return segments.some((segment) => SENSITIVE_PATH_SEGMENTS.has(segment.toLowerCase()));
220
166
  }
221
- /**
222
- * Returns true when `absolutePath` is the root itself or one of its
223
- * descendants after both paths have been resolved.
224
- */
225
167
  function isPathWithinRoot(absolutePath, root) {
226
168
  const relative = path_1.default.relative(root, absolutePath);
227
169
  return (relative === '' ||
@@ -229,25 +171,6 @@ function isPathWithinRoot(absolutePath, root) {
229
171
  !relative.startsWith('..') &&
230
172
  !path_1.default.isAbsolute(relative)));
231
173
  }
232
- /**
233
- * Copy one agent-planned asset file into a variant worktree at the
234
- * project-relative `destination`. The agent decides routing
235
- * (`destination` like `public/assets/avatar.glb`) so all variants share
236
- * a consistent layout. Fails loudly when the source is missing or the
237
- * destination tries to escape the worktree — silent fallbacks here
238
- * would re-introduce the broken-asset failure mode this routing is
239
- * supposed to prevent.
240
- *
241
- * Security: `entry.source` comes from `report_source_plan` and is
242
- * agent-controlled. To prevent a prompt-injected source plan from
243
- * exfiltrating arbitrary readable host files (SSH keys, dotfiles,
244
- * cloud credentials, project secrets) into the generated app, the
245
- * source must (1) be an absolute path that resolves via realpath
246
- * (no traversal, no symlinks pointing outside the resolved location),
247
- * (2) be a regular file (not a device, socket, fifo, or directory),
248
- * (3) live under the approved asset root, (4) have an extension on the
249
- * asset allowlist.
250
- */
251
174
  function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
252
175
  if (!assetSourceRoot) {
253
176
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source requires an approved asset root before copying '${entry.source}'`);
@@ -255,14 +178,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
255
178
  if (!path_1.default.isAbsolute(assetSourceRoot)) {
256
179
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetSourceRoot must be an absolute path, got '${assetSourceRoot}'`);
257
180
  }
258
- // A relative source is resolved against the approved asset root. The
259
- // agent-facing protocol requires the source to live under that root but not
260
- // to be absolute, and the root path is internal to Rivet (a staged context
261
- // bundle) — so a relative name such as 'avatar.glb' is the natural, safe
262
- // form. Every downstream guard (symlink, extension, within-root, sensitive
263
- // segments) runs against this resolved absolute path, so the resolution
264
- // cannot widen what is copyable: a relative `..` escape still fails the
265
- // within-root check below.
266
181
  const absoluteSource = path_1.default.isAbsolute(entry.source)
267
182
  ? entry.source
268
183
  : path_1.default.resolve(assetSourceRoot, entry.source);
@@ -270,10 +185,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
270
185
  if (!ALLOWED_INERT_ASSET_EXTENSIONS.has(ext)) {
271
186
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source extension '${ext || '(none)'}' is not on the allowlist (got '${entry.source}'). Only inert media/font/document assets may be copied.`);
272
187
  }
273
- // lstat first: a symlink whose target lies outside the source path
274
- // could otherwise smuggle in arbitrary files. Reject symlinks outright;
275
- // realpath would resolve them but the user-visible intent of an
276
- // assetPlan entry is to name a concrete file.
277
188
  let lstat;
278
189
  try {
279
190
  lstat = fs_1.default.lstatSync(absoluteSource);
@@ -287,9 +198,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
287
198
  if (!lstat.isFile()) {
288
199
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source must be a regular file: ${entry.source}`);
289
200
  }
290
- // Resolve realpath as additional defense: even with no symlinks at the
291
- // leaf, an intermediate directory could be a symlink. Cross-check the
292
- // file kind on the resolved path.
293
201
  let resolvedSource;
294
202
  try {
295
203
  resolvedSource = fs_1.default.realpathSync(absoluteSource);
@@ -308,24 +216,9 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
308
216
  if (!resolvedStat.isFile()) {
309
217
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source resolved target must be a regular file: ${entry.source}`);
310
218
  }
311
- // Containment is the security boundary and must be checked before any
312
- // sensitive-segment scan. The approved asset root is system-chosen and
313
- // trusted (a staged context bundle), and its realpath can legitimately
314
- // pass through a "sensitive" segment that is NOT agent-controlled — on
315
- // macOS `fs.realpathSync(os.tmpdir())` resolves to `/private/var/folders/...`,
316
- // so the temp-staged root contains `private`. A symlinked intermediate dir
317
- // that forwards into a sensitive ancestor (e.g. `<asset-root>/avatar -> ~/.ssh`)
318
- // pushes the realpath OUTSIDE the root and is rejected here.
319
219
  if (!isPathWithinRoot(resolvedSource, resolvedAssetSourceRoot)) {
320
220
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source must stay inside the approved asset root: ${entry.source}`);
321
221
  }
322
- // Sensitive-segment defense, scoped to the agent-controlled portion BELOW
323
- // the trusted root. Only this relative remainder is chosen by the agent's
324
- // source plan, so a sensitive segment it introduces under the root (a real
325
- // `<asset-root>/.ssh/key.glb`, or a within-root symlink that realpaths into
326
- // one) is still refused, while the trusted root prefix is never scanned.
327
- // `resolvedSource` is the fully symlink-resolved real path, so the scan
328
- // covers what the file actually resolves to, not just its literal name.
329
222
  const relativeResolvedSource = path_1.default.relative(resolvedAssetSourceRoot, resolvedSource);
330
223
  if (hasSensitivePathSegment(relativeResolvedSource)) {
331
224
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source traverses a sensitive directory and is refused: ${entry.source}`);
@@ -343,7 +236,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
343
236
  fs_1.default.copyFileSync(resolvedSource, absDest);
344
237
  }
345
238
  const defaultPreviewQaRunner = ({ html }) => (0, previewQa_1.runPreviewQa)({ html });
346
- /** Disabled-reason copy for a variant whose preview cannot be opened. */
347
239
  const buildViewDisabledReason = (args) => {
348
240
  if (args.status === 'failed') {
349
241
  return args.qa?.summary ?? 'Generation failed';
@@ -367,11 +259,9 @@ const DESIGN_CREATION_ACTION_RE = /\b(create|build|design|make|redesign|refresh|
367
259
  const DESIGN_CREATION_SURFACE_RE = /\b(home\s?page|landing page|dashboard|screen|site|website|app|page|ui|interface|component|hero)\b/i;
368
260
  const NON_VISUAL_CHANGE_RE = /\b(api|backend|database|event|lint|query|server|test|tracking|typecheck)\b/i;
369
261
  const DIFF_CAPTURE_FAILURE_SUMMARY = 'Unable to verify the generated design diff; regenerate this variant so Rivet can confirm source changes.';
370
- /** Separates invalid worker output from a Rivet check that could not run. */
371
262
  const qaFailureErrorCode = (qa) => qa.issues.some((issue) => issue.kind === 'verification_unavailable')
372
263
  ? 'VARIANT_VERIFICATION_UNAVAILABLE'
373
264
  : 'VARIANT_QA_FAILED';
374
- /** Identifies a repair-triggering completion across transport retries. */
375
265
  const repairCompletionKey = (args) => JSON.stringify([args.workItemId, args.leaseId, args.attempt, 'succeeded']);
376
266
  const briefLabelKey = (value) => value.trim().toLowerCase().replace(/\s+/g, ' ');
377
267
  const truncateBriefLabel = (value) => {
@@ -452,17 +342,6 @@ const isDesignCreationCodeGenInput = (input, prompt) => {
452
342
  return (DESIGN_CREATION_ACTION_RE.test(text) &&
453
343
  DESIGN_CREATION_SURFACE_RE.test(text));
454
344
  };
455
- /**
456
- * Wraps SessionStore for the operations that have side effects: approve
457
- * (provision worktrees), reportComplete (capture diff), commit (apply picked
458
- * output), cancel (teardown). Pure read paths bypass and call SessionStore
459
- * directly.
460
- *
461
- * This is the terminal-native variant of the orchestrator: the user picks
462
- * a single brief upfront, so there's only ever one code-gen item per
463
- * session and no live preview / proxy retarget. Once the agent reports
464
- * the variant succeeded, the CLI can commit the chosen output directly.
465
- */
466
345
  class AgentVariantsOrchestrator {
467
346
  store;
468
347
  worktrees;
@@ -479,31 +358,9 @@ class AgentVariantsOrchestrator {
479
358
  activeVariantServerIdleTtlMs;
480
359
  devServerRestartDelayMs;
481
360
  resources = new Map();
482
- /**
483
- * Committed dev servers from prior sessions that survived teardown. The
484
- * orchestrator outlives any single session — once a new session starts, the
485
- * prior committed dev server is no longer needed (the next session opens
486
- * its own preview chip), so stop it before the new session's first preview
487
- * goes live. Keyed by sessionId for diagnostics; values are kept alive
488
- * intentionally between commit and next `propose` / `shutdown`.
489
- */
490
361
  lingeringCommittedDevServers = new Map();
491
- /**
492
- * Per-session in-flight commit chain. Two overlapping commitVariant calls
493
- * would otherwise both pass the `getVariantPick` idempotency check (the
494
- * pick isn't recorded until after `applyDiffToProject`) and double-invoke
495
- * `git apply` — which corrupts the working tree on the second run. The
496
- * chain serializes commits per session so the second caller waits for the
497
- * first to finish and then hits the idempotency check (returning
498
- * `duplicate: true` for the same variantId, or `PENDING_CHANGE_CONFLICT`
499
- * for a different one).
500
- */
501
362
  inflightCommits = new Map();
502
- /** Most recent agent-variants sessionId — read by the iframe chip via
503
- * GET /api/variants/active. Cleared on cancel or commit. */
504
363
  activeSessionId = null;
505
- /** Push channel for the iframe chip's SSE subscription. Emits an
506
- * ActiveSnapshot on every state change so the chip never has to poll. */
507
364
  events = new events_1.EventEmitter();
508
365
  constructor(deps) {
509
366
  this.store = deps.store;
@@ -526,11 +383,7 @@ class AgentVariantsOrchestrator {
526
383
  this.devServerRestartDelayMs =
527
384
  deps.devServerRestartDelayMs ?? DEV_SERVER_RESTART_DELAY_MS;
528
385
  }
529
- // --- Pure delegations (no side effects) ---------------------------------
530
386
  propose(args) {
531
- // A new session means any lingering committed dev server from a prior
532
- // session is no longer needed — the next session opens its own preview.
533
- // Best-effort stop; failures here don't block propose.
534
387
  void this.stopLingeringCommittedDevServers().catch((err) => {
535
388
  log.warn('Stopping lingering committed dev servers failed', err);
536
389
  });
@@ -577,36 +430,18 @@ class AgentVariantsOrchestrator {
577
430
  this.emitChange();
578
431
  return result;
579
432
  }
580
- /** Returns the most recent agent-variants sessionId (or null). */
581
433
  getActiveSessionId() {
582
434
  return this.activeSessionId;
583
435
  }
584
- /** Subscribe to active-snapshot pushes. Returns an unsubscribe fn. */
585
436
  subscribeToEvents(listener) {
586
437
  this.events.on('change', listener);
587
438
  return () => {
588
439
  this.events.off('change', listener);
589
440
  };
590
441
  }
591
- /** Number of live Rivet UI clients subscribed to the variants SSE stream.
592
- * A subscribed client means a Rivet page is open in the browser. */
593
442
  uiClientCount = 0;
594
- /** Wall-clock of the last UI-client connect/disconnect. `hasUiClients`
595
- * treats a very recent disconnect as still-connected to ride out the brief
596
- * gap when an EventSource drops and auto-reconnects (default retry ~3s) —
597
- * otherwise a `propose`/`start` landing in that window reads zero clients
598
- * and spawns a duplicate browser tab. */
599
443
  lastUiClientActivityAt = 0;
600
- /** Grace window covering an EventSource reconnect (its default retry is ~3s;
601
- * the SSE heartbeat is 30s). Long enough to span a reconnect, short enough
602
- * that a genuine page close frees the "reopen on next propose" path quickly. */
603
444
  static UI_CLIENT_GRACE_MS = 6000;
604
- /**
605
- * Register a live Rivet UI client (called when the variants SSE stream opens).
606
- * Returns a release fn to call on disconnect. Used as the "a Rivet page is
607
- * already open" signal so the MCP server can avoid spawning a duplicate tab
608
- * every time the variants flow re-enters an already-active editor session.
609
- */
610
445
  registerUiClient() {
611
446
  this.uiClientCount += 1;
612
447
  this.lastUiClientActivityAt = Date.now();
@@ -620,8 +455,6 @@ class AgentVariantsOrchestrator {
620
455
  this.lastUiClientActivityAt = Date.now();
621
456
  };
622
457
  }
623
- /** True when at least one Rivet UI page is currently connected — or one
624
- * disconnected within the grace window (an EventSource mid-reconnect). */
625
458
  hasUiClients() {
626
459
  if (this.uiClientCount > 0)
627
460
  return true;
@@ -630,21 +463,17 @@ class AgentVariantsOrchestrator {
630
463
  return (Date.now() - this.lastUiClientActivityAt <
631
464
  AgentVariantsOrchestrator.UI_CLIENT_GRACE_MS);
632
465
  }
633
- /** @effect Records activity for the current variants session, if one exists. */
634
466
  touchActiveSession() {
635
467
  if (!this.activeSessionId)
636
468
  return;
637
469
  this.touchSession(this.activeSessionId);
638
470
  }
639
- /** @effect Resets idle cleanup for active variant preview servers. */
640
471
  touchSession(sessionId) {
641
472
  const resources = this.resources.get(sessionId);
642
473
  if (!resources || resources.cleanupStarted)
643
474
  return;
644
475
  this.scheduleActivePreviewIdleTimer(resources);
645
476
  }
646
- /** Build the snapshot the chip cares about. Reads from SessionStore +
647
- * per-resource state; safe to call at any time. */
648
477
  buildActiveSnapshot() {
649
478
  const sessionId = this.activeSessionId;
650
479
  if (!sessionId || !this.store.hasSession(sessionId)) {
@@ -683,22 +512,12 @@ class AgentVariantsOrchestrator {
683
512
  ...(workerRuntime ? { workerRuntime } : {}),
684
513
  };
685
514
  }
686
- /** Record which worker runtime this session's current batch leases to —
687
- * called by the generation services right after the lease-owner decision
688
- * so `variants start`/status can answer "what is running these?". */
689
515
  setWorkerRuntime(sessionId, summary) {
690
516
  if (!this.store.hasSession(sessionId))
691
517
  return;
692
518
  this.store.setWorkerRuntime(sessionId, summary);
693
- // Push a fresh snapshot to SSE subscribers: startUnified/requestWork
694
- // already emitted before this setter ran, and without an emit here a
695
- // subscribed client would not see workerRuntime until the next state
696
- // transition (possibly the first worker completion).
697
519
  this.emitChange();
698
520
  }
699
- /** User reference files stored in the work item's context bundle (uploaded
700
- * or copied local images). Surfaced on the snapshot so briefings can point
701
- * workers at the files directly — one Read instead of a bundle walk. */
702
521
  static contextFilesOf(context) {
703
522
  const files = (context?.userContext ?? [])
704
523
  .filter((source) => source.transport === 'file')
@@ -1050,8 +869,6 @@ class AgentVariantsOrchestrator {
1050
869
  if (projectContext.variantContext) {
1051
870
  (0, variantContext_1.writeVariantContextBundle)(projectContext.variantContext);
1052
871
  }
1053
- // Source-context quality is now measured off the raw context bundle plus
1054
- // the action metadata the agent reported, not the legacy summary fields.
1055
872
  const bundle = projectContext.kind === 'fresh'
1056
873
  ? projectContext.variantContext
1057
874
  : undefined;
@@ -1113,9 +930,6 @@ class AgentVariantsOrchestrator {
1113
930
  }
1114
931
  throw error;
1115
932
  }
1116
- // Record lease times so variant_completed can report lease→report
1117
- // duration. (We don't fire a separate code_gen_leased event — the
1118
- // funnel signal we care about is per-variant completion duration.)
1119
933
  const resources = this.resources.get(args.sessionId);
1120
934
  if (resources) {
1121
935
  const now = Date.now();
@@ -1125,10 +939,6 @@ class AgentVariantsOrchestrator {
1125
939
  }
1126
940
  this.writeLeasedWorkItemBriefings(args.sessionId, result.leasedWorkItems.map((item) => item.id));
1127
941
  this.trackRefinementLeased({ sessionId: args.sessionId, lease: result });
1128
- // Decorate each leased item's input with the worktreePath provisioned
1129
- // by approve(). The skill instructs agents to write files to
1130
- // `input.worktreePath` — without this decoration that field would be
1131
- // missing and the agent would have no idea where to edit.
1132
942
  const decorated = {
1133
943
  ...result,
1134
944
  leasedWorkItems: result.leasedWorkItems.map((item) => {
@@ -1145,7 +955,6 @@ class AgentVariantsOrchestrator {
1145
955
  this.emitChange();
1146
956
  return decorated;
1147
957
  }
1148
- /** @effect Copies caller-supplied context assets into each leased workspace. */
1149
958
  materializeContextAssets(sessionId, items) {
1150
959
  const resources = this.ensureResources(sessionId);
1151
960
  for (const item of items) {
@@ -1166,10 +975,6 @@ class AgentVariantsOrchestrator {
1166
975
  resources.contextAssets.set(item.id, (0, contextAssets_1.materializeContextAssets)({ assets, workspace, previewKind }));
1167
976
  }
1168
977
  }
1169
- /**
1170
- * @effect Records how an existing project's worktrees will be previewed so
1171
- * context assets receive references that resolve on that serving surface.
1172
- */
1173
978
  async resolveContextAssetPreviewKind(sessionId) {
1174
979
  const resources = this.ensureResources(sessionId);
1175
980
  try {
@@ -1182,13 +987,6 @@ class AgentVariantsOrchestrator {
1182
987
  log.warn(`Failed to resolve context asset preview kind for ${sessionId}; using dev-server references`, error);
1183
988
  }
1184
989
  }
1185
- /**
1186
- * @effect Writes each leased implementation item's server-authored briefing
1187
- * BESIDE its workspace so the coordinating host dispatches workers with a
1188
- * short pointer prompt instead of composing prose per worker. Best-effort:
1189
- * a briefing write failure never blocks the lease (the host guidance's
1190
- * packet fields still carry the same data).
1191
- */
1192
990
  writeLeasedWorkItemBriefings(sessionId, leasedWorkItemIds) {
1193
991
  if (leasedWorkItemIds.length === 0)
1194
992
  return;
@@ -1218,13 +1016,9 @@ class AgentVariantsOrchestrator {
1218
1016
  }
1219
1017
  }
1220
1018
  }
1221
- /** @effect Assigns isolated, server-owned artifact workspaces to leased static work. */
1222
1019
  ensureStaticWorkspaces(sessionId, items) {
1223
1020
  const resources = this.ensureResources(sessionId);
1224
1021
  const projectContext = this.store.getProjectContext(sessionId);
1225
- // This lane provisions by copying the source artifact tree (vary forks) or
1226
- // seeding an entry file — it bypasses provisionWorktrees, so it gets its
1227
- // own provisioning telemetry here.
1228
1022
  const provisionStartedAt = Date.now();
1229
1023
  let assignedCount = 0;
1230
1024
  for (const item of items) {
@@ -1271,7 +1065,6 @@ class AgentVariantsOrchestrator {
1271
1065
  });
1272
1066
  }
1273
1067
  }
1274
- /** Reads a completed static artifact while enforcing its assigned directory boundary. */
1275
1068
  readAssignedStaticArtifact(sessionId, workItemId) {
1276
1069
  const workspaceManager = this.resources.get(sessionId)?.workspaceManager;
1277
1070
  if (!workspaceManager) {
@@ -1281,15 +1074,7 @@ class AgentVariantsOrchestrator {
1281
1074
  }
1282
1075
  beginStaticPreviewRefinements(args) {
1283
1076
  const seenVariantIds = new Set();
1284
- // Targets whose in-place refinement could neither be created nor folded
1285
- // into a pending one (e.g. the variant was already sent). We finish the
1286
- // batch's other targets, then RETURN these so the caller can surface them
1287
- // in its response — rather than throwing (which would break the agent poll
1288
- // and lose the already-consumed batch) or silently dropping them.
1289
1077
  const droppedRefinements = [];
1290
- // Work items THIS batch created, so the caller can tell the agent to lease
1291
- // exactly these — letting concurrent runs (several watchers) each pick up
1292
- // their own batch instead of one greedily leasing everything.
1293
1078
  const createdWorkItemIds = [];
1294
1079
  for (const target of args.targets) {
1295
1080
  if (seenVariantIds.has(target.variantId))
@@ -1310,9 +1095,6 @@ class AgentVariantsOrchestrator {
1310
1095
  });
1311
1096
  const currentHtml = this.getStaticPreviewHtml(args.sessionId, target.variantId);
1312
1097
  if (target.count == null) {
1313
- // Plain Apply (no variantRequest) → refine the variant IN PLACE: one
1314
- // edit that overwrites the source, no new sibling cards. Only an
1315
- // explicit "Vary" (which carries a count) fans out new variants.
1316
1098
  try {
1317
1099
  const refineItem = this.store.createRefineVariantWorkItem({
1318
1100
  sessionId: args.sessionId,
@@ -1327,8 +1109,6 @@ class AgentVariantsOrchestrator {
1327
1109
  createdWorkItemIds.push(refineItem.id);
1328
1110
  }
1329
1111
  catch (error) {
1330
- // A refinement is already queued for this variant — fold the newer
1331
- // instruction in rather than dropping it (mirrors the apply queue).
1332
1112
  if (error instanceof errors_1.AgentVariantsError &&
1333
1113
  error.code === 'PENDING_CHANGE_CONFLICT') {
1334
1114
  const folded = this.store.appendPendingRefineVariantInstruction({
@@ -1338,8 +1118,6 @@ class AgentVariantsOrchestrator {
1338
1118
  fidelity: target.fidelity,
1339
1119
  });
1340
1120
  if (!folded) {
1341
- // Nothing to fold into — the conflict is terminal (the variant
1342
- // was already sent / is no longer editable). Don't swallow it.
1343
1121
  droppedRefinements.push({
1344
1122
  variantId: target.variantId,
1345
1123
  reason: error.message,
@@ -1359,9 +1137,6 @@ class AgentVariantsOrchestrator {
1359
1137
  }
1360
1138
  continue;
1361
1139
  }
1362
- // "Vary" fans out: create `count` NEW sibling variants seeded from the
1363
- // source HTML + instruction, rather than overwriting the source in place.
1364
- // The agent leases them through the standard request-work path.
1365
1140
  try {
1366
1141
  const forks = this.store.createForkedStaticPreviewWorkItems({
1367
1142
  sessionId: args.sessionId,
@@ -1379,11 +1154,6 @@ class AgentVariantsOrchestrator {
1379
1154
  createdWorkItemIds.push(...forks.map((item) => item.id));
1380
1155
  }
1381
1156
  catch (error) {
1382
- // Terminal conflict — the source is no longer editable, or a variant
1383
- // was already sent for this session (the fork path has nothing to fold
1384
- // into). Surface it structurally like the in-place branch instead of
1385
- // throwing, which would break the agent poll AND lose this batch (the
1386
- // server already consumed it from the FIFO before calling us).
1387
1157
  if (error instanceof errors_1.AgentVariantsError &&
1388
1158
  (error.code === 'PENDING_CHANGE_CONFLICT' ||
1389
1159
  error.code === 'VARIANT_NOT_EDITABLE')) {
@@ -1410,24 +1180,6 @@ class AgentVariantsOrchestrator {
1410
1180
  this.emitChange();
1411
1181
  return { droppedRefinements, createdWorkItemIds };
1412
1182
  }
1413
- /**
1414
- * Adopt a PAST variant (from a prior session's persisted history) into the
1415
- * active session, rehydrating it from its on-disk static snapshot so the
1416
- * comment / refine / Vary machinery treats it as a live, first-class variant.
1417
- *
1418
- * Triggered when the user makes their first edit on a selected past direction.
1419
- * The store appends an already-`succeeded` `static_preview` work item keyed by
1420
- * the past identity (idempotent); this method registers the matching static-
1421
- * preview record so {@link getStaticPreviewHtml}, {@link getVariants}
1422
- * (preview.kind = 'static_artifact', view enabled), and the
1423
- * `/api/variants/:sid/static/:vid` routes all light up exactly as they do for a
1424
- * freshly-generated static_preview variant.
1425
- *
1426
- * `filesDir` is the absolute path to the persisted `files/` snapshot and
1427
- * `entryPath` is its selected HTML document. Returns the stable active-session
1428
- * `workItemId` so the caller can route the triggering edit to it, plus whether
1429
- * it was already adopted.
1430
- */
1431
1183
  async adoptPastVariant(args) {
1432
1184
  const { assetBase, hasAssets } = await this.resolveAdoptedStaticPreviewFiles(args.filesDir, args.entryPath);
1433
1185
  const append = this.store.appendAdoptedStaticVariant({
@@ -1445,8 +1197,6 @@ class AgentVariantsOrchestrator {
1445
1197
  requestedCount: 1,
1446
1198
  sourceVariantId: args.source.variantId,
1447
1199
  });
1448
- // Register (or re-register, harmlessly) the static-preview record so the
1449
- // snapshot surfaces the adopted variant as a static_artifact.
1450
1200
  const resources = this.ensureResources(args.sessionId);
1451
1201
  resources.staticPreviews.set(append.workItemId, {
1452
1202
  workItemId: append.workItemId,
@@ -1471,11 +1221,6 @@ class AgentVariantsOrchestrator {
1471
1221
  alreadyAdopted: !append.created,
1472
1222
  };
1473
1223
  }
1474
- /**
1475
- * Rehydrate a static history variant into the current active session when it
1476
- * can still accept edits; otherwise create a replacement active session whose
1477
- * only visible direction is the selected history artifact.
1478
- */
1479
1224
  async bootstrapPastVariantSession(args) {
1480
1225
  const usableSessionId = this.getUsableActiveSessionId();
1481
1226
  if (usableSessionId) {
@@ -1556,12 +1301,6 @@ class AgentVariantsOrchestrator {
1556
1301
  }
1557
1302
  return { assetBase, hasAssets };
1558
1303
  }
1559
- /**
1560
- * True when the variant is an HTML-only static_preview work item. Adopted past
1561
- * variants and fresh `static_preview` variants both qualify. Existing-project
1562
- * `code_gen` variants can still expose a static artifact for preview, but Vary
1563
- * must keep those on the worktree-backed code_gen append path.
1564
- */
1565
1304
  isStaticPreviewVariant(sessionId, workItemId) {
1566
1305
  try {
1567
1306
  return (this.store.getWorkItemKind(sessionId, workItemId) === 'static_preview');
@@ -1570,11 +1309,6 @@ class AgentVariantsOrchestrator {
1570
1309
  return false;
1571
1310
  }
1572
1311
  }
1573
- /**
1574
- * Resolve the history source for a forked Vary row. If the immediate parent
1575
- * is an adopted past direction, collapse against that original history row;
1576
- * otherwise collapse against the same-session parent variant.
1577
- */
1578
1312
  resolveHistoryParentVariant(sessionId, sourceVariantId) {
1579
1313
  if (!sourceVariantId)
1580
1314
  return undefined;
@@ -1641,10 +1375,6 @@ class AgentVariantsOrchestrator {
1641
1375
  workItemCount: 1,
1642
1376
  instructionLength: args.instruction.length,
1643
1377
  });
1644
- // Lease the just-created refine item by id. A generic
1645
- // requestWork({ requestedLeaseCount: 1 }) takes the first leasable item in
1646
- // work-item order, which could be an unrelated still-pending static_preview
1647
- // rather than this refinement.
1648
1378
  return this.requestWork({
1649
1379
  sessionId: args.sessionId,
1650
1380
  leaseOwner: args.leaseOwner,
@@ -1657,7 +1387,6 @@ class AgentVariantsOrchestrator {
1657
1387
  getWorkItemInput(sessionId, workItemId) {
1658
1388
  return this.store.getWorkItemInput(sessionId, workItemId);
1659
1389
  }
1660
- /** Returns status after orchestration QA and refinement post-processing. */
1661
1390
  getWorkItemStatus(sessionId, workItemId) {
1662
1391
  return this.store.getWorkItemStatus(sessionId, workItemId);
1663
1392
  }
@@ -1674,16 +1403,10 @@ class AgentVariantsOrchestrator {
1674
1403
  const resources = this.resources.get(sessionId);
1675
1404
  return this.store.getVariants(sessionId).map((variant) => {
1676
1405
  const port = this.getDevServerPort(sessionId, variant.workItemId);
1677
- // Captured worktree diff (existing-project code_gen). Surfaced as a
1678
- // changed-files count so a diff-only variant (no dev server / static
1679
- // artifact) still reads as a real result in the panel.
1680
1406
  const capturedDiff = resources?.worktrees.get(variant.workItemId)?.diff;
1681
1407
  const changedFilesCount = typeof capturedDiff === 'string' && capturedDiff.length > 0
1682
1408
  ? countDiffFiles(capturedDiff)
1683
1409
  : undefined;
1684
- // For fresh sessions, static_preview items ARE the variants — look up
1685
- // directly by workItemId. Fall back to briefId search for existing-project
1686
- // sessions where code_gen items were paired with companion static_preview items.
1687
1410
  const staticPreview = resources?.staticPreviews.get(variant.workItemId) ??
1688
1411
  this.getStaticPreviewByBriefId(sessionId, variant.briefId);
1689
1412
  let preview;
@@ -1694,11 +1417,6 @@ class AgentVariantsOrchestrator {
1694
1417
  };
1695
1418
  }
1696
1419
  else if (!port) {
1697
- // handleSucceededReport is fire-and-forget so staticPreviews may not be
1698
- // populated yet when getVariants is called (e.g. in the terminal response).
1699
- // item.output is set synchronously by store.reportComplete, so it's always
1700
- // available. Read it directly as a fallback so previewUrls in terminal
1701
- // responses include the variant that just triggered terminal state.
1702
1420
  try {
1703
1421
  const output = this.store.getWorkItemOutput(sessionId, variant.workItemId);
1704
1422
  if (typeof output?.html === 'string' && output.html.length > 0) {
@@ -1709,7 +1427,6 @@ class AgentVariantsOrchestrator {
1709
1427
  }
1710
1428
  }
1711
1429
  catch {
1712
- /* work item may not exist in edge cases */
1713
1430
  }
1714
1431
  }
1715
1432
  if (!preview && port) {
@@ -1719,9 +1436,6 @@ class AgentVariantsOrchestrator {
1719
1436
  const isSucceeded = variant.status === 'succeeded';
1720
1437
  const qaFailed = qa?.status === 'failed';
1721
1438
  const canView = Boolean(preview) || (isSucceeded && Boolean(port));
1722
- // A succeeded variant with no live preview whose dev server we tried and
1723
- // failed to start: surface the cause so the UI can show an accurate
1724
- // per-direction message instead of the generic disconnected overlay.
1725
1439
  const previewFailure = resources?.previewFailures.get(variant.workItemId);
1726
1440
  const previewUnavailable = !canView && isSucceeded && previewFailure
1727
1441
  ? {
@@ -1765,36 +1479,19 @@ class AgentVariantsOrchestrator {
1765
1479
  hasSession(sessionId) {
1766
1480
  return this.store.hasSession(sessionId);
1767
1481
  }
1768
- /** Read the projectContext for a session — used by Express routes that
1769
- * build the chip snapshot via `stateForSession`. */
1770
1482
  getProjectContext(sessionId) {
1771
1483
  return this.store.getProjectContext(sessionId);
1772
1484
  }
1773
- /** Resolve a worktree path for a code-gen work item, if provisioned. */
1774
1485
  getWorktreePath(sessionId, workItemId) {
1775
1486
  return this.resources.get(sessionId)?.worktrees.get(workItemId)
1776
1487
  ?.worktreePath;
1777
1488
  }
1778
- /**
1779
- * Resolve the project cwd inside a worktree so subdirectory projects run
1780
- * from the same repo-relative location.
1781
- */
1782
1489
  getProjectCwdInWorktree(worktreePath) {
1783
1490
  return this.worktrees.getProjectCwdInWorktree(worktreePath);
1784
1491
  }
1785
- /** Resolve the dev server port for a code-gen work item, if running. */
1786
1492
  getDevServerPort(sessionId, workItemId) {
1787
1493
  return this.resources.get(sessionId)?.worktrees.get(workItemId)?.port;
1788
1494
  }
1789
- /**
1790
- * Restores a Rivet-owned preview after idle reclamation or an explicit retry
1791
- * of a failed start. Reuses the saved worktree without leasing generation work.
1792
- *
1793
- * @effect Clears the idle marker and prior crash budget, starts the worktree
1794
- * dev server, and emits preview-state snapshots.
1795
- * @deps Uses the live session resources, project context, and dev-server
1796
- * manager owned by this orchestrator.
1797
- */
1798
1495
  async restoreVariantPreview(sessionId, workItemId, options = {}) {
1799
1496
  const resources = this.resources.get(sessionId);
1800
1497
  const record = resources?.worktrees.get(workItemId);
@@ -1836,10 +1533,6 @@ class AgentVariantsOrchestrator {
1836
1533
  record.previewRestoration = undefined;
1837
1534
  }
1838
1535
  }
1839
- /**
1840
- * @effect Resolves the dev server port for a preview request and refreshes
1841
- * active-preview retention for that session while the port is still live.
1842
- */
1843
1536
  resolveDevServerPortForPreview(sessionId, workItemId) {
1844
1537
  const port = this.getDevServerPort(sessionId, workItemId);
1845
1538
  if (typeof port === 'number') {
@@ -1847,14 +1540,6 @@ class AgentVariantsOrchestrator {
1847
1540
  }
1848
1541
  return port;
1849
1542
  }
1850
- /**
1851
- * True work-item kind for a variant, or undefined when the session/item is
1852
- * unknown. This is the authoritative routing signal for Vary/refine intakes:
1853
- * an existing-project `code_gen` variant materialized as a static preview
1854
- * (registerExistingStaticPreview) DISPLAYS as `static_artifact` and serves
1855
- * HTML, but must fork via the code_gen/worktree path — HTML presence is not
1856
- * a valid discriminator.
1857
- */
1858
1543
  getVariantWorkItemKind(sessionId, workItemId) {
1859
1544
  try {
1860
1545
  return this.store.getWorkItemKind(sessionId, workItemId);
@@ -1864,9 +1549,6 @@ class AgentVariantsOrchestrator {
1864
1549
  }
1865
1550
  }
1866
1551
  getStaticPreviewHtml(sessionId, workItemId) {
1867
- // Primary: read the materialized entry from the variant's per-variant
1868
- // directory (written by handleSucceededReport). The directory is the source
1869
- // of truth for the static deliverable.
1870
1552
  const preview = this.resources
1871
1553
  .get(sessionId)
1872
1554
  ?.staticPreviews.get(workItemId);
@@ -1877,12 +1559,8 @@ class AgentVariantsOrchestrator {
1877
1559
  return fromDisk;
1878
1560
  }
1879
1561
  catch {
1880
- // fall through to the work-item output fallback below
1881
1562
  }
1882
1563
  }
1883
- // Fallback: read directly from the work item's stored output — available
1884
- // as soon as reportComplete runs, before handleSucceededReport fires (so
1885
- // the per-variant directory may not exist yet).
1886
1564
  try {
1887
1565
  const output = this.store.getWorkItemOutput(sessionId, workItemId);
1888
1566
  return typeof output?.html === 'string' && output.html.length > 0
@@ -1893,38 +1571,20 @@ class AgentVariantsOrchestrator {
1893
1571
  return undefined;
1894
1572
  }
1895
1573
  }
1896
- /** Resolve the DESIGN.md markdown behind an artifact link. */
1897
1574
  getDesignContextMarkdown(sessionId, artifactId) {
1898
1575
  const artifact = findDesignContextArtifact(this.store.getProjectContext(sessionId), artifactId);
1899
1576
  return artifact?.content;
1900
1577
  }
1901
- /** Build the rendered DesignMD document for an artifact link. */
1902
1578
  getDesignContextViewerHtml(sessionId, artifactId) {
1903
1579
  const artifact = findDesignContextArtifact(this.store.getProjectContext(sessionId), artifactId);
1904
1580
  return artifact ? buildDesignContextViewerDocument(artifact) : undefined;
1905
1581
  }
1906
- /**
1907
- * `true` when the variant has a non-empty `assetBase` — i.e. its inlined
1908
- * HTML references sibling files served by the asset route. The route
1909
- * uses this to decide whether to inject a `<base href>` (only needed
1910
- * when relative URLs in the HTML must resolve against the asset
1911
- * sub-path). Self-contained HTML keeps its natural URL resolution.
1912
- */
1913
1582
  hasStaticPreviewAssets(sessionId, workItemId) {
1914
1583
  const record = this.resources
1915
1584
  .get(sessionId)
1916
1585
  ?.staticPreviews.get(workItemId);
1917
1586
  return Boolean(record?.hasAssets);
1918
1587
  }
1919
- /**
1920
- * Resolve an absolute, sandboxed path for a sibling asset that the
1921
- * variant's inlined HTML references (e.g. `./avatar.glb`, `./hero.png`).
1922
- * Returns `undefined` when the variant has no `assetBase`, the requested
1923
- * path escapes the base (path traversal), or the file does not exist.
1924
- *
1925
- * Used by the `/api/variants/:sessionId/static/:variantId/<asset>` route
1926
- * to serve assets from the agent's on-disk variant workspace pre-commit.
1927
- */
1928
1588
  resolveStaticPreviewAssetPath(sessionId, workItemId, requestedPath) {
1929
1589
  const record = this.resources
1930
1590
  .get(sessionId)
@@ -1933,12 +1593,6 @@ class AgentVariantsOrchestrator {
1933
1593
  return undefined;
1934
1594
  if (!requestedPath || requestedPath.length === 0)
1935
1595
  return undefined;
1936
- // Resolve against the variant's own directory first so any asset the agent
1937
- // actually wrote/modified wins. Only when the worktree clone lacks the file
1938
- // do we fall back to the host project root — that recovers git-ignored or
1939
- // binary assets the worktree provisioning couldn't carry over, which the
1940
- // original preview already serves (see `assetFallbackBase`). Both roots are
1941
- // held to the identical traversal/realpath/hardlink sandbox.
1942
1596
  return (resolveAssetWithinBase(record.assetBase, requestedPath) ??
1943
1597
  (record.assetFallbackBase
1944
1598
  ? resolveAssetWithinBase(record.assetFallbackBase, requestedPath)
@@ -1955,7 +1609,6 @@ class AgentVariantsOrchestrator {
1955
1609
  const safeWorkItemId = encodeURIComponent(workItemId);
1956
1610
  return `/api/variants/${safeSessionId}/static/${safeWorkItemId}`;
1957
1611
  }
1958
- // --- Mutation wrappers (state + side effects) ---------------------------
1959
1612
  async approve(args) {
1960
1613
  const result = this.store.approve(args);
1961
1614
  const resources = this.ensureResources(args.sessionId);
@@ -1976,11 +1629,6 @@ class AgentVariantsOrchestrator {
1976
1629
  workItemIds,
1977
1630
  });
1978
1631
  this.emitChange();
1979
- // Await provisioning before returning so request_work always sees a
1980
- // populated worktreePath on each leased item. Provisioning creates a
1981
- // git worktree and copies dependencies for each variant, and the
1982
- // agent has nothing useful to do between approve and request_work
1983
- // anyway — running them serially is the contract the skill assumes.
1984
1632
  try {
1985
1633
  if (projectContext.kind === 'existing') {
1986
1634
  await this.resolveContextAssetPreviewKind(args.sessionId);
@@ -1994,50 +1642,18 @@ class AgentVariantsOrchestrator {
1994
1642
  }
1995
1643
  return result;
1996
1644
  }
1997
- /**
1998
- * Unified one-call kickoff that collapses propose → report_briefs →
1999
- * approve. Uses AI-authored briefs supplied by agent callers, with a
2000
- * deterministic prompt-derived fallback for human-direct calls, and
2001
- * immediately approves so the session lands in `work_items_ready`.
2002
- *
2003
- * Supports both existing-project sessions (spawns code_gen work items
2004
- * for the agent to lease) and zero-to-one sessions (spawns
2005
- * static_preview work items; the server runs scaffold_base in the
2006
- * background). This is the single-call path; source-grounded zero-to-one
2007
- * sessions (source URLs / inspiration extraction) run through `propose`
2008
- * instead so the source-research flow can gate generation — start_variants
2009
- * routes them there. This method does not run source research.
2010
- *
2011
- * Host-agnostic: no LLM calls happen here. The agent (Claude Code,
2012
- * Cursor, Codex) generates the label and code when it leases the
2013
- * work items via continue_variants(action="request_work").
2014
- */
2015
1645
  async startUnified(args) {
2016
1646
  const count = args.briefs?.length ?? args.count ?? contracts_1.DEFAULT_VARIANT_COUNT;
2017
1647
  const projectContext = args.projectContext ?? {
2018
1648
  kind: 'existing',
2019
1649
  };
2020
1650
  const designContextCount = projectContext.designContext?.length ?? 0;
2021
- // Fresh source-grounded sessions (a captured context bundle on a fresh
2022
- // project) must run through `propose` so the source-research/source_plan
2023
- // flow gates generation; start_variants routes them there before reaching
2024
- // here, so this guard is an internal invariant. Existing-project sessions
2025
- // keep the single-call path even with a bundle — they have no source_plan
2026
- // stage, and the bundle's raw context is threaded straight into code_gen.
2027
- // Brief-driven fresh starts are exempt for the same reason: the caller
2028
- // already did its source research when it authored the briefs, so the
2029
- // bundle is raw worker context (reference images), not research input.
2030
1651
  const isSourceGrounded = projectContext.kind === 'fresh' &&
2031
1652
  Boolean(projectContext.variantContext) &&
2032
1653
  !args.briefs?.length;
2033
1654
  if (isSourceGrounded) {
2034
1655
  throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'Source-grounded sessions must run through the source-research flow (propose), not the single-call startUnified path.');
2035
1656
  }
2036
- // A second "Vary" on an existing project that still has a live session
2037
- // ACCUMULATES into that session instead of starting a fresh one that
2038
- // would orphan the prior variants (and overwrite `activeSessionId`, so
2039
- // the RHS would only ever show the latest batch). Gated to existing
2040
- // projects so fresh 0→1 generation is unaffected.
2041
1657
  const appendSessionId = args.allowAccumulate &&
2042
1658
  projectContext.kind === 'existing' &&
2043
1659
  projectContext.projectPath
@@ -2075,8 +1691,6 @@ class AgentVariantsOrchestrator {
2075
1691
  };
2076
1692
  const { createdWorkItemIds } = this.store.appendCodeGenVariants({
2077
1693
  ...forkArgs,
2078
- // Fork parent (Vary on a variant): seeds each new worktree from the
2079
- // parent's tree instead of the base tree. Absent for a plain append.
2080
1694
  ...(args.sourceVariantId
2081
1695
  ? { sourceVariantId: args.sourceVariantId }
2082
1696
  : {}),
@@ -2115,8 +1729,6 @@ class AgentVariantsOrchestrator {
2115
1729
  projectContext,
2116
1730
  runLabel: args.runLabel,
2117
1731
  ...(args.fidelity ? { fidelity: args.fidelity } : {}),
2118
- // Briefs land via reportBriefs immediately below — never enter the
2119
- // source-plan stage, even for a fresh session carrying a bundle.
2120
1732
  hasPreparedBriefs: true,
2121
1733
  ...(args.sessionId ? { sessionId: args.sessionId } : {}),
2122
1734
  });
@@ -2147,18 +1759,11 @@ class AgentVariantsOrchestrator {
2147
1759
  });
2148
1760
  sessionId = proposeResult.sessionId;
2149
1761
  scaffoldBaseWorkItemId = approveResult.scaffoldBaseWorkItemId ?? null;
2150
- // For existing-project sessions, approve() returns the new code_gen
2151
- // ids in codeGenWorkItemIds. For zero-to-one, approve() spawns
2152
- // static_preview items instead — those ids aren't in codeGenWorkItemIds,
2153
- // so read them out of the active-variants snapshot which covers both
2154
- // kinds. Snapshot order mirrors brief order (insertion order).
2155
1762
  variantIds =
2156
1763
  projectContext.kind === 'fresh'
2157
1764
  ? this.store.getVariants(sessionId).map((v) => v.workItemId)
2158
1765
  : approveResult.codeGenWorkItemIds;
2159
1766
  }
2160
- // Stamp the UI correlation id so the panel maps its optimistic placeholders
2161
- // to these real cards (the same mechanism the static-preview fork uses).
2162
1767
  if (args.requestId) {
2163
1768
  this.store.assignVariantRequestId(sessionId, variantIds, args.requestId);
2164
1769
  }
@@ -2192,8 +1797,6 @@ class AgentVariantsOrchestrator {
2192
1797
  const lease = this.requestWork({
2193
1798
  sessionId,
2194
1799
  leaseOwner: args.leaseOwner,
2195
- // Append: lease ONLY the new batch so a still-leasable prior item
2196
- // (e.g. a re-leased one) isn't swept into this Vary's lease.
2197
1800
  ...(appendSessionId ? { workItemIds: variantIds } : {}),
2198
1801
  });
2199
1802
  leaseId = lease.leaseId;
@@ -2209,15 +1812,6 @@ class AgentVariantsOrchestrator {
2209
1812
  leasedWorkItems,
2210
1813
  };
2211
1814
  }
2212
- /**
2213
- * Build the per-variant briefs for a unified start. Supplied briefs keep
2214
- * meaningful direction labels, while duplicate or empty labels are made
2215
- * unique against the visible session rows. The fallback derives a short
2216
- * run-intent label from the prompt (e.g. "make it brighter" →
2217
- * "Brighter 1/2/…") rather than an indistinct "Variant N". `uniqueBriefIds`
2218
- * is set for the append path so the new batch's briefIds can't collide with
2219
- * the live session's existing ones.
2220
- */
2221
1815
  buildUnifiedBriefs(args) {
2222
1816
  const briefId = (i) => args.uniqueBriefIds ? `v-${(0, crypto_1.randomUUID)().slice(0, 8)}` : `v${i + 1}`;
2223
1817
  const runLabel = args.runLabel?.trim() || (0, runLabel_1.deriveRunLabel)(args.prompt);
@@ -2247,13 +1841,6 @@ class AgentVariantsOrchestrator {
2247
1841
  body: synthesizeUnifiedBriefBody(args.prompt, i + 1, args.count),
2248
1842
  }, i));
2249
1843
  }
2250
- /**
2251
- * The active sessionId IF it is an existing-project session for `projectPath`
2252
- * that can still accept appended variants — i.e. not committed, not
2253
- * cancelled/failed. Returns null otherwise, so start_variants falls back to
2254
- * creating a fresh session (first Vary, a different project, or after the
2255
- * prior session was committed/cancelled).
2256
- */
2257
1844
  getAppendableExistingSessionId(projectPath) {
2258
1845
  const sessionId = this.activeSessionId;
2259
1846
  if (!sessionId || !this.store.hasSession(sessionId))
@@ -2268,7 +1855,6 @@ class AgentVariantsOrchestrator {
2268
1855
  return null;
2269
1856
  return sessionId;
2270
1857
  }
2271
- /** @effect Registers a provisioned git worktree with runtime and workspace state. */
2272
1858
  async registerWorktreeWorkspace(resources, record) {
2273
1859
  let projectPath = record.worktreePath;
2274
1860
  try {
@@ -2284,15 +1870,6 @@ class AgentVariantsOrchestrator {
2284
1870
  projectPath,
2285
1871
  });
2286
1872
  }
2287
- /**
2288
- * Provision a worktree for each appended existing-project variant. Mirrors
2289
- * {@link provisionExistingWorktrees} but only for the newly appended ids, and
2290
- * passes a per-batch `instanceKeyPrefix` so the new worktree dirs do not
2291
- * collide with the first batch's `${sessionId}-${i}` paths.
2292
- */
2293
- /** Emits provisioning started/completed/failed telemetry around `run` for
2294
- * the vary-fork/append lanes that bypass provisionWorktrees (and its
2295
- * telemetry). Rethrows failures untouched. */
2296
1873
  async withProvisioningTelemetry(args, run) {
2297
1874
  const startedAt = Date.now();
2298
1875
  this.telemetry.track('agent_variants.provisioning_started', {
@@ -2347,11 +1924,6 @@ class AgentVariantsOrchestrator {
2347
1924
  })));
2348
1925
  });
2349
1926
  }
2350
- /**
2351
- * Provision worktrees for a code_gen Vary forked from a parent variant.
2352
- * Copies the parent's worktree tree so each sibling starts from the parent's
2353
- * diff rather than git HEAD / Original.
2354
- */
2355
1927
  async provisionForkedFromVariantWorktrees(sessionId, sourceVariantId, workItemIds) {
2356
1928
  if (workItemIds.length === 0)
2357
1929
  return;
@@ -2359,13 +1931,14 @@ class AgentVariantsOrchestrator {
2359
1931
  if (!sourcePath) {
2360
1932
  throw new errors_1.AgentVariantsError('VARIANT_NOT_EDITABLE', `Cannot fork from variant ${sourceVariantId}: no worktree path`);
2361
1933
  }
2362
- if (!this.worktrees.forkWorktreesFrom) {
1934
+ const forkWorktreesFrom = this.worktrees.forkWorktreesFrom?.bind(this.worktrees);
1935
+ if (!forkWorktreesFrom) {
2363
1936
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'worktreeManager does not implement forkWorktreesFrom');
2364
1937
  }
2365
1938
  await this.withProvisioningTelemetry({ sessionId, kind: 'forked_variant', variantCount: workItemIds.length }, async () => {
2366
1939
  const resources = this.ensureResources(sessionId);
2367
1940
  const instanceKeyPrefix = `f${(0, crypto_1.randomUUID)().slice(0, 8)}-`;
2368
- const paths = await withProvisionTimeout(this.worktrees.forkWorktreesFrom(sourcePath, sessionId, workItemIds.length, instanceKeyPrefix), this.provisionTimeoutMs);
1941
+ const paths = await withProvisionTimeout(forkWorktreesFrom(sourcePath, sessionId, workItemIds.length, instanceKeyPrefix), this.provisionTimeoutMs);
2369
1942
  await Promise.all(workItemIds.map((id, index) => this.registerWorktreeWorkspace(resources, {
2370
1943
  workItemId: id,
2371
1944
  worktreePath: paths[index],
@@ -2373,15 +1946,7 @@ class AgentVariantsOrchestrator {
2373
1946
  });
2374
1947
  }
2375
1948
  async reportComplete(args) {
2376
- // Phase-timing anchor: lease→report (agent work) vs report→recorded
2377
- // (QA gate + post-processing) are attributed separately on
2378
- // `variant_completed` so latency work can tell them apart.
2379
1949
  const reportReceivedAt = Date.now();
2380
- // Cooperative abort short-circuit: if the work item was removed/cancelled
2381
- // while in flight (delete-while-loading, cancel_variant, session cancel),
2382
- // skip the schema and QA gates entirely — there is no point validating or
2383
- // QA-ing output we are about to discard — and hand back the store's
2384
- // `aborted` signal so the agent stops this work item now.
2385
1950
  if (this.store.hasSession(args.sessionId) &&
2386
1951
  this.store.isWorkItemAborted(args.sessionId, args.workItemId)) {
2387
1952
  return this.store.reportComplete(args);
@@ -2405,9 +1970,6 @@ class AgentVariantsOrchestrator {
2405
1970
  output: this.readAssignedStaticArtifact(args.sessionId, args.workItemId),
2406
1971
  }
2407
1972
  : args;
2408
- // Contract validation keeps internal callers that provide an explicit
2409
- // static output honest. Host workers complete assigned artifacts without
2410
- // transporting the HTML through this report.
2411
1973
  if (resolvedArgs.status === 'succeeded' &&
2412
1974
  this.store.hasSession(args.sessionId) &&
2413
1975
  (workItemKind === 'static_preview' ||
@@ -2425,27 +1987,15 @@ class AgentVariantsOrchestrator {
2425
1987
  }
2426
1988
  throw new errors_1.AgentVariantsError('SCHEMA_VALIDATION_FAILED', `${workItemKind} output.html must be a string and non-empty when explicit output is provided. Host workers should write the assigned index.html instead.`);
2427
1989
  }
2428
- // Check Rivet-owned output integrity synchronously before recording
2429
- // success. A terminal failure uses `VARIANT_QA_FAILED` so the variant never
2430
- // reaches `ready` and `getVariants` can disable its commit action.
2431
1990
  const qaStartedAt = Date.now();
2432
1991
  const qaEval = workItemKind === 'refine_variant'
2433
1992
  ? null
2434
1993
  : await this.evaluateQaForReport(resolvedArgs);
2435
1994
  const qaMs = qaEval === null ? null : Date.now() - qaStartedAt;
2436
- // A `retry` verdict re-leases the variant for one structural repair instead
2437
- // of recording success, so short-circuit the normal record path.
2438
1995
  if (qaEval?.decision === 'retry') {
2439
1996
  return this.handleQaRegenRetry(resolvedArgs, qaEval.qa);
2440
1997
  }
2441
1998
  let effectiveArgs = qaEval?.decision === 'fail_terminal' ? qaEval.overrideArgs : resolvedArgs;
2442
- // For a successful refine_variant, swap the refined static preview into
2443
- // place and persist history BEFORE recording success in the store. This
2444
- // keeps the user-visible `refinement.status: succeeded` (and the snapshot
2445
- // emitted below) from ever being observable while the variant still serves
2446
- // stale HTML. If post-processing throws, convert the report to `failed` so
2447
- // the agent/UI surface the failure instead of a success pointing at
2448
- // unrefreshed output.
2449
1999
  if (workItemKind === 'refine_variant' &&
2450
2000
  effectiveArgs.status === 'succeeded') {
2451
2001
  try {
@@ -2492,9 +2042,6 @@ class AgentVariantsOrchestrator {
2492
2042
  throw error;
2493
2043
  }
2494
2044
  this.emitChange();
2495
- // Per-variant telemetry on terminal item statuses (skip 'running'
2496
- // heartbeats and the brief work item — only code_gen / scaffold_base
2497
- // matter for the funnel).
2498
2045
  if (effectiveArgs.status === 'succeeded' ||
2499
2046
  effectiveArgs.status === 'failed' ||
2500
2047
  effectiveArgs.status === 'cancelled') {
@@ -2503,11 +2050,8 @@ class AgentVariantsOrchestrator {
2503
2050
  const durationMs = leasedAt !== undefined ? Date.now() - leasedAt : null;
2504
2051
  const approveStartedAt = resources?.approveStartedAt;
2505
2052
  const approveToCompleteMs = approveStartedAt !== undefined ? Date.now() - approveStartedAt : null;
2506
- // Byte size of generated output for HTML vs full-stack comparison.
2507
2053
  const outputBytes = estimateOutputBytes(effectiveArgs.output);
2508
2054
  const projectContextKind = this.store.getProjectContext(args.sessionId).kind;
2509
- // Execution mode mirrors the host work-item snapshot derivation so
2510
- // prod latency can finally segment vary vs create vs refine.
2511
2055
  const mode = workItemKind !== undefined && isImplementationWorkItemKind(workItemKind)
2512
2056
  ? this.store.isVaryForkWorkItem(args.sessionId, args.workItemId)
2513
2057
  ? 'vary'
@@ -2523,15 +2067,11 @@ class AgentVariantsOrchestrator {
2523
2067
  approveToCompleteMs,
2524
2068
  kind: workItemKind ?? null,
2525
2069
  mode,
2526
- // Phase split of `durationMs`: agent work vs server-side gating.
2527
2070
  leaseToReportMs: leasedAt !== undefined ? reportReceivedAt - leasedAt : null,
2528
2071
  reportProcessingMs: Date.now() - reportReceivedAt,
2529
2072
  qaMs,
2530
2073
  hasError: Boolean(effectiveArgs.error),
2531
2074
  errorCode: effectiveArgs.error?.code ?? null,
2532
- // Failure detail + API status ride the event so field failures are
2533
- // diagnosable from telemetry alone (the July 2026 EXECUTOR_WORKER_FAILED
2534
- // incident took an hour of forensics for want of these).
2535
2075
  errorMessage: effectiveArgs.error?.message ?? null,
2536
2076
  errorApiStatus: effectiveArgs.error?.apiErrorStatus ?? null,
2537
2077
  isScaffold: resources?.scaffoldBaseWorkItemId === args.workItemId,
@@ -2617,10 +2157,6 @@ class AgentVariantsOrchestrator {
2617
2157
  log.error(`handleSucceededReport failed for ${args.sessionId}/${args.workItemId}`, err);
2618
2158
  });
2619
2159
  }
2620
- // Teardown is deferred to commitVariant / cancel. Terminal stage just
2621
- // means all variants are done; the user still needs to review and pick
2622
- // one. Resources (worktrees + captured diffs) live until that pick lands
2623
- // on the bridge.
2624
2160
  return result;
2625
2161
  }
2626
2162
  async cancel(args) {
@@ -2651,13 +2187,6 @@ class AgentVariantsOrchestrator {
2651
2187
  });
2652
2188
  return result;
2653
2189
  }
2654
- /**
2655
- * Cancel a single variant within a session. Siblings continue. Idempotent
2656
- * on terminal states. Per-variant worktree teardown is deferred to a
2657
- * follow-up; the lease is released, so requestWork won't re-surface this
2658
- * variant and the agent's report_variant_complete for it (if it lands
2659
- * after cancellation) is rejected by the stale-lease check.
2660
- */
2661
2190
  async cancelVariant(args) {
2662
2191
  const result = this.store.cancelWorkItem({
2663
2192
  sessionId: args.sessionId,
@@ -2687,12 +2216,6 @@ class AgentVariantsOrchestrator {
2687
2216
  alreadyTerminal: result.alreadyTerminal,
2688
2217
  };
2689
2218
  }
2690
- /**
2691
- * Remove a variant from the UI. Hides it from the active snapshot for good
2692
- * (it's filtered out of progress/summary/terminal accounting too) while
2693
- * retaining it in `.rivet/variants/` with status `removed` so the work is
2694
- * kept, never rendered again. Mirrors `cancelVariant`'s shape; idempotent.
2695
- */
2696
2219
  async removeVariant(args) {
2697
2220
  const result = this.store.removeWorkItem({
2698
2221
  sessionId: args.sessionId,
@@ -2720,13 +2243,6 @@ class AgentVariantsOrchestrator {
2720
2243
  alreadyRemoved: result.alreadyRemoved,
2721
2244
  };
2722
2245
  }
2723
- /**
2724
- * Rename a variant's user-visible title. Patches the in-memory work item so
2725
- * the next snapshot carries the new label, persists it to the variant's
2726
- * `.rivet/variants/` manifest (best-effort — a never-persisted variant simply
2727
- * skips the disk write), and pushes the updated snapshot over SSE. Mirrors
2728
- * `removeVariant`'s shape.
2729
- */
2730
2246
  async renameVariant(args) {
2731
2247
  const result = this.store.renameWorkItem({
2732
2248
  sessionId: args.sessionId,
@@ -2737,7 +2253,6 @@ class AgentVariantsOrchestrator {
2737
2253
  source: 'mcp',
2738
2254
  sessionId: args.sessionId,
2739
2255
  variantId: args.variantId,
2740
- // Telemetry policy: never the raw agent/user label text, only its length.
2741
2256
  labelLength: args.label.length,
2742
2257
  sessionStage: result.sessionStage,
2743
2258
  });
@@ -2752,10 +2267,6 @@ class AgentVariantsOrchestrator {
2752
2267
  sessionStage: result.sessionStage,
2753
2268
  };
2754
2269
  }
2755
- /**
2756
- * Rename a run folder: re-home one request batch in a single store pass,
2757
- * persist each affected manifest best-effort, and push one updated snapshot.
2758
- */
2759
2270
  async renameRun(args) {
2760
2271
  const result = this.store.renameRun({
2761
2272
  sessionId: args.sessionId,
@@ -2766,7 +2277,6 @@ class AgentVariantsOrchestrator {
2766
2277
  this.telemetry.track('agent_variants.run_renamed', {
2767
2278
  source: 'mcp',
2768
2279
  sessionId: args.sessionId,
2769
- // Telemetry policy: never the raw label text, only its length.
2770
2280
  runLabelLength: args.label.length,
2771
2281
  renamedCount: result.workItemIds.length,
2772
2282
  sessionStage: result.sessionStage,
@@ -2785,18 +2295,7 @@ class AgentVariantsOrchestrator {
2785
2295
  sessionStage: result.sessionStage,
2786
2296
  };
2787
2297
  }
2788
- /**
2789
- * User has reviewed the rendered variants and picked one. Look up the
2790
- * captured diff or generated project, apply it to the destination, and record
2791
- * the pick. Idempotent on (sessionId, variantId): repeating the call returns
2792
- * duplicate=true without applying again.
2793
- */
2794
2298
  async commitVariant(args) {
2795
- // Serialize per-session so two overlapping commits can't both run
2796
- // `applyDiffToProject` (or the fresh rename) before the first records
2797
- // its pick. The second caller waits for the first to settle, then runs
2798
- // commitVariantImpl which hits the idempotency check in
2799
- // `getVariantPick` / `recordVariantPick`.
2800
2299
  const prior = this.inflightCommits.get(args.sessionId);
2801
2300
  const run = (async () => {
2802
2301
  if (prior) {
@@ -2825,17 +2324,8 @@ class AgentVariantsOrchestrator {
2825
2324
  }
2826
2325
  }
2827
2326
  async commitVariantImpl(args) {
2828
- // Idempotent path — SessionStore.recordVariantPick is the source of truth
2829
- // for which variant the user picked. If the same variant is being
2830
- // committed again, replay the previously stored envelope's metadata
2831
- // without going back through resources (which may have been torn down).
2832
2327
  const existingPick = this.store.getVariantPick(args.sessionId);
2833
2328
  if (existingPick && existingPick.variantId === args.variantId) {
2834
- // Retry-safe history flip. If the first commit attempt applied
2835
- // successfully but the history-persist task crashed, the chosen variant
2836
- // stays at `completed` instead of `committed` on disk. Re-run the flip on
2837
- // every duplicate attempt; the terminal-status guard in `markStatus`
2838
- // makes this safely idempotent.
2839
2329
  const projectContext = this.store.getProjectContext(args.sessionId);
2840
2330
  let historyProjectPath;
2841
2331
  if (projectContext.kind === 'fresh') {
@@ -2861,9 +2351,6 @@ class AgentVariantsOrchestrator {
2861
2351
  log.warn(`persistVariantHistoryAtCommit (duplicate retry) failed for session ${args.sessionId}`, err);
2862
2352
  });
2863
2353
  }
2864
- // If the committed dev/static server is still running (either tracked
2865
- // on resources, or handed off to the lingering registry), surface its
2866
- // URL so a retry restores the iframe to the live project.
2867
2354
  const lingering = this.lingeringCommittedDevServers.get(args.sessionId);
2868
2355
  const live = this.resources.get(args.sessionId)?.committedDevServer;
2869
2356
  const replayPort = lingering?.port ?? live?.port;
@@ -2898,19 +2385,9 @@ class AgentVariantsOrchestrator {
2898
2385
  let envelopeDestination;
2899
2386
  let changedFilesCount;
2900
2387
  let runnablePaths;
2901
- // Port of the committed dev/static server, when one was spawned during
2902
- // this commit. Surfaced on the response as `previewUrl` so the UI can
2903
- // restore the iframe to the committed project without falling through to
2904
- // the auto-static fallback.
2905
2388
  let committedPreviewPort;
2906
2389
  if (projectContext.kind === 'fresh') {
2907
2390
  const destinationPath = projectContext.workspacePath;
2908
- // Realpath the destination ONCE for both the empty-check (below) and
2909
- // the static_preview flatten step (further down). Computing it twice
2910
- // could diverge if the path's realpath status changes between calls
2911
- // (e.g. the directory was a symlink during the empty check but got
2912
- // resolved between then and `mkdirSync`). `undefined` means realpath
2913
- // failed — caller branches treat that as "no canonical form known".
2914
2391
  let realDestination;
2915
2392
  try {
2916
2393
  realDestination = fs_1.default.realpathSync(destinationPath);
@@ -2918,34 +2395,13 @@ class AgentVariantsOrchestrator {
2918
2395
  catch {
2919
2396
  realDestination = undefined;
2920
2397
  }
2921
- // Read the commit policy off the canonical run plan rather than
2922
- // re-deriving from executionPlan.mode. `materialize_project` is the
2923
- // vite_app lane (rename/copy the whole worktree); `write_static_site`
2924
- // is the static_preview lane (inline HTML + sibling assets).
2925
2398
  const commitPolicy = (0, runPlan_1.resolveRunPlanPolicy)(projectContext).commit;
2926
2399
  const isViteApp = commitPolicy === 'materialize_project';
2927
- // vite_app: strict emptiness check — that lane renames a worktree into
2928
- // destinationPath and would clobber user files.
2929
- // static_preview: the agent intentionally wrote sibling assets under
2930
- // workspacePath (via `output.assetBase`) before reporting succeeded —
2931
- // those per-variant subdirs ARE the deliverable. Allow exactly the
2932
- // assetBase entries known to this session; anything else still
2933
- // triggers DESTINATION_NOT_EMPTY.
2934
2400
  if (isViteApp) {
2935
2401
  this.assertDestinationAvailable(destinationPath);
2936
2402
  }
2937
2403
  else {
2938
- // Compare assetBase entries (which are realpath'd by
2939
- // resolveStaticPreviewAssetBase) against the realpath'd destination
2940
- // — on macOS `/tmp` is a symlink to `/private/tmp`, and a raw
2941
- // string comparison would falsely reject every entry.
2942
2404
  const compareBase = realDestination ?? destinationPath;
2943
- // When ANY variant's assetBase is the destination itself (the agent
2944
- // wrote files directly at the workspace root rather than under a
2945
- // per-variant subdir), the empty-check would treat the agent's own
2946
- // deliverable as foreign content. Skip the check in that case — the
2947
- // workspace IS the deliverable; commit will overwrite index.html
2948
- // below.
2949
2405
  const anyAssetBaseIsDestination = [
2950
2406
  ...resources.staticPreviews.values(),
2951
2407
  ].some((sp) => sp.assetBase === compareBase);
@@ -2960,16 +2416,6 @@ class AgentVariantsOrchestrator {
2960
2416
  }
2961
2417
  }
2962
2418
  if (isViteApp) {
2963
- // Vite_app: the deliverable is the entire variant worktree, not a
2964
- // single HTML file. When the worktree lives on the same volume as
2965
- // the destination (the common case — provisionFreshWorktrees scaffolds
2966
- // under destinationParent/.rivet-variants/) we can rename it into
2967
- // place. That moves the entire tree — including the materialized
2968
- // node_modules — in O(1) with no copy, and the rename is atomic.
2969
- // For cross-volume cases (user passed a destinationParent on a
2970
- // different mount than the .rivet-variants dir, e.g. tests stubbing
2971
- // workspacePath to a tmp dir), fall back to the recursive-copy +
2972
- // background-install path so the feature still works.
2973
2419
  const record = resources.worktrees.get(args.variantId);
2974
2420
  if (!record) {
2975
2421
  throw new errors_1.AgentVariantsError('WORK_ITEM_NOT_FOUND', `Unknown variantId ${args.variantId} for session ${args.sessionId}`);
@@ -2978,18 +2424,6 @@ class AgentVariantsOrchestrator {
2978
2424
  let isDependencyInstallRequired = false;
2979
2425
  try {
2980
2426
  if (areSameVolume(record.worktreePath, destinationPath)) {
2981
- // Vite's dev server writes its module cache to `<worktreePath>/.vite/`
2982
- // and recreates that directory on the fly whenever it's missing. If
2983
- // we rename a worktree out from under a running dev server, Vite
2984
- // will materialize an empty `.vite/` shell back at the OLD path —
2985
- // leaving behind orphan stub dirs in `.rivet-variants/` and
2986
- // confusing later cleanup. Stop every variant's dev server first
2987
- // (including the chosen variant, which is about to move) so no
2988
- // process is holding the old paths open during the rename.
2989
- //
2990
- // We stop them eagerly here rather than relying on teardownSession
2991
- // because teardown runs AFTER the rename — too late to prevent the
2992
- // stub-dir race.
2993
2427
  await this.stopAllDevServersForSession(resources);
2994
2428
  isDependencyInstallRequired = await resolveNodeModulesSymlink(record.worktreePath);
2995
2429
  await this.renameWorktreeIntoDestination(record.worktreePath, destinationPath);
@@ -3005,21 +2439,6 @@ class AgentVariantsOrchestrator {
3005
2439
  }
3006
2440
  changedFilesCount = countWorktreeFiles(destinationPath);
3007
2441
  if (!usedRename) {
3008
- // Cross-volume fallback: materializeProject excludes node_modules
3009
- // so we have to re-install at the destination. Don't await the
3010
- // install — the agent's commit_variant call should return
3011
- // immediately — but chain the dev-server start to it so the iframe
3012
- // recovers without manual intervention once deps are ready.
3013
- //
3014
- // NOTE: `committedPreviewPort` stays undefined on this branch by
3015
- // design — the install + start sequence takes minutes, far longer
3016
- // than the response can wait. The iframe's `switchPreviewPort`
3017
- // callback (invoked from `startCommittedDevServer` when the
3018
- // server finally comes up) retargets the proxy then, so the
3019
- // iframe reaches the new server without the URL being on the
3020
- // commit response. The response surface stays `previewUrl?:` (the
3021
- // field is optional) and consumers fall back to the proxy
3022
- // upstream when it's absent.
3023
2442
  void this.installDependencies(destinationPath)
3024
2443
  .then(() => this.startCommittedDevServer({
3025
2444
  resources,
@@ -3033,9 +2452,6 @@ class AgentVariantsOrchestrator {
3033
2452
  await this.installDependencies(destinationPath);
3034
2453
  }
3035
2454
  if (usedRename) {
3036
- // Preserve the unchosen variants as runnable siblings of the
3037
- // chosen project. Best-effort: failures here log and continue so
3038
- // a partial history never blocks the commit handoff.
3039
2455
  try {
3040
2456
  runnablePaths = this.preserveUnchosenVariants({
3041
2457
  sessionId: args.sessionId,
@@ -3046,12 +2462,6 @@ class AgentVariantsOrchestrator {
3046
2462
  catch (err) {
3047
2463
  log.warn(`preserveUnchosenVariants failed for session ${args.sessionId}; continuing without history`, err);
3048
2464
  }
3049
- // Stopped every dev server pre-rename to dodge the .vite/ stub-dir
3050
- // race. The iframe is still pointed at the (now-dead) chosen
3051
- // variant's port via the proxy, so without a fresh server at the
3052
- // destination the user would see "preview disconnected" the moment
3053
- // they commit. Spawn one and retarget the proxy. Best-effort: if
3054
- // it fails, the user can `npm run dev` themselves at destination.
3055
2465
  committedPreviewPort = await this.startCommittedDevServer({
3056
2466
  resources,
3057
2467
  destinationPath,
@@ -3069,18 +2479,7 @@ class AgentVariantsOrchestrator {
3069
2479
  envelopeDestination = destinationPath;
3070
2480
  }
3071
2481
  else {
3072
- // Static_preview: HTML is the entire deliverable. Write index.html.
3073
- // Prefer the in-memory record; fall back to the persisted history at
3074
- // `<workspacePath>/.rivet/variants/<sessionId>/<variantId>/files/index.html`
3075
- // so a process restart between report_variant_complete and commit
3076
- // doesn't strand the variant.
3077
2482
  const staticPreview = resources.staticPreviews.get(args.variantId);
3078
- // Resolve the committed index.html before the flatten step below
3079
- // moves/removes the per-variant dir. `getStaticPreviewHtml` reads the
3080
- // materialized `<dir>/index.html` and falls back to the work-item's
3081
- // stored output (the reported HTML) when the on-disk file is missing
3082
- // or empty — so a failed materialization still commits real content
3083
- // rather than an empty file.
3084
2483
  const htmlFromDir = staticPreview
3085
2484
  ? this.getStaticPreviewHtml(args.sessionId, args.variantId)
3086
2485
  : undefined;
@@ -3094,21 +2493,6 @@ class AgentVariantsOrchestrator {
3094
2493
  }
3095
2494
  try {
3096
2495
  fs_1.default.mkdirSync(destinationPath, { recursive: true });
3097
- // If the chosen variant has an `assetBase` subdir under
3098
- // destinationPath (e.g. `<workspace>/var-1` containing
3099
- // `avatar.glb`), move its contents up to the destination root so
3100
- // the committed HTML can reference them as `./avatar.glb`. Then
3101
- // delete every OTHER static_preview record's assetBase — the
3102
- // unchosen variants' sibling assets are no longer relevant once
3103
- // the user picked. Both steps run before the canonical index.html
3104
- // is written so the chosen variant's on-disk index.html (if any)
3105
- // gets overwritten by the inlined version below.
3106
- // assetBase entries are realpath'd; compare against the realpath
3107
- // of destinationPath so symlink-stripped paths line up (macOS:
3108
- // `/tmp` → `/private/tmp`). `realDestination` was computed once
3109
- // at the top of the fresh branch — re-realpath in case `mkdirSync`
3110
- // above just created the directory (the initial computation may
3111
- // have returned undefined when the dir didn't yet exist).
3112
2496
  let flattenBase = realDestination;
3113
2497
  if (!flattenBase) {
3114
2498
  try {
@@ -3119,32 +2503,17 @@ class AgentVariantsOrchestrator {
3119
2503
  }
3120
2504
  }
3121
2505
  const chosenAssetBase = staticPreview?.assetBase;
3122
- // Skip flattening when assetBase IS the destination — the agent
3123
- // wrote files directly at the workspace root, so there's no subdir
3124
- // to flatten. Only move when assetBase is a strict descendant.
3125
2506
  if (chosenAssetBase &&
3126
2507
  isStrictlyInside(chosenAssetBase, flattenBase)) {
3127
2508
  for (const entry of fs_1.default.readdirSync(chosenAssetBase)) {
3128
2509
  const src = path_1.default.join(chosenAssetBase, entry);
3129
2510
  const dst = path_1.default.join(flattenBase, entry);
3130
- // Self-collision guard: when an agent names a child the same
3131
- // as the parent dir (e.g. `var-1/var-1/`), `dst` resolves to
3132
- // `chosenAssetBase` itself. The rmSync below would then delete
3133
- // the parent — including every remaining entry we're about to
3134
- // move — and the next iteration's `renameSync` would fail
3135
- // with ENOENT. The agent's last attempted variant would also
3136
- // be silently dropped. Skip this entry; we still rm the
3137
- // parent at the end of the loop.
3138
2511
  if (path_1.default.resolve(dst) === path_1.default.resolve(chosenAssetBase)) {
3139
2512
  continue;
3140
2513
  }
3141
2514
  if (fs_1.default.existsSync(dst)) {
3142
2515
  fs_1.default.rmSync(dst, { recursive: true, force: true });
3143
2516
  }
3144
- // Cross-volume safety: rename fails with EXDEV when src and
3145
- // dst are on different mounts (possible when the user's
3146
- // workspacePath crosses a symlink to another volume). Fall
3147
- // back to recursive copy + remove so the commit doesn't die.
3148
2517
  try {
3149
2518
  fs_1.default.renameSync(src, dst);
3150
2519
  }
@@ -3173,10 +2542,6 @@ class AgentVariantsOrchestrator {
3173
2542
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `Failed to write static preview to ${destinationPath}: ${message}`);
3174
2543
  }
3175
2544
  changedFilesCount = countWorktreeFiles(destinationPath);
3176
- // Spawn a static file server at destinationPath and retarget the
3177
- // proxy so the iframe stays live across commit (parity with the
3178
- // vite_app rename path). Best-effort: a failure leaves the iframe
3179
- // showing "preview disconnected" but doesn't fail the commit.
3180
2545
  committedPreviewPort = await this.startCommittedDevServer({
3181
2546
  resources,
3182
2547
  destinationPath,
@@ -3192,10 +2557,6 @@ class AgentVariantsOrchestrator {
3192
2557
  }
3193
2558
  }
3194
2559
  else {
3195
- // Existing project: diff against the user's repo. resolveEnv lives in
3196
- // this branch only — fresh sessions don't have a user-supplied project
3197
- // and the bridge.getProjectPath() it reads from would either be stale
3198
- // or empty for them.
3199
2560
  const env = await this.resolveEnv(args.sessionId);
3200
2561
  const record = resources.worktrees.get(args.variantId);
3201
2562
  if (!record) {
@@ -3205,8 +2566,6 @@ class AgentVariantsOrchestrator {
3205
2566
  throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Variant ${args.variantId} has no captured diff yet — wait for report_variant_complete(succeeded) first`);
3206
2567
  }
3207
2568
  changedFilesCount = countDiffFiles(record.diff);
3208
- // Apply the diff to the user's working tree so the variant lands on the
3209
- // current branch uncommitted.
3210
2569
  if (!this.worktrees.applyDiffToProject) {
3211
2570
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'WorktreeManager does not support applying diffs to the project tree');
3212
2571
  }
@@ -3234,17 +2593,10 @@ class AgentVariantsOrchestrator {
3234
2593
  changedFilesCount,
3235
2594
  payload,
3236
2595
  };
3237
- // Record the pick in the SessionStore so future commitVariant calls with
3238
- // the same variantId are idempotent and a different variantId returns
3239
- // PENDING_CHANGE_CONFLICT (already picked).
3240
2596
  this.store.recordVariantPick({
3241
2597
  sessionId: args.sessionId,
3242
2598
  envelope,
3243
2599
  });
3244
- // History: flip every persisted variant in this session to its terminal
3245
- // status. Variants are persisted at code_gen success time; this patches
3246
- // the status and destinationPath for the chosen one. Best-effort, never
3247
- // blocks the commit.
3248
2600
  const historyProjectPath = projectContext.kind === 'fresh'
3249
2601
  ? projectContext.workspacePath
3250
2602
  : envelopeDestination;
@@ -3262,13 +2614,6 @@ class AgentVariantsOrchestrator {
3262
2614
  log.warn(`persistVariantHistoryAtCommit failed for session ${args.sessionId}`, err);
3263
2615
  }
3264
2616
  resources.committedVariantIds.add(args.variantId);
3265
- // For fresh `new-project` commits the committed variant IS the user's
3266
- // final result — there's no dev server to fall back to. Keep the session
3267
- // active so SSE keeps pushing snapshots with the chosen variant; the UI's
3268
- // iframe stays on it instead of unmounting to about:blank (which would
3269
- // surface a misleading "Preview isn't connected" overlay). For diff /
3270
- // diff-applied commits the user moves on to their own dev server, so
3271
- // clearing is correct — that's the original behavior preserved below.
3272
2617
  if (this.activeSessionId === args.sessionId &&
3273
2618
  payload.kind !== 'project-created') {
3274
2619
  this.activeSessionId = null;
@@ -3288,9 +2633,6 @@ class AgentVariantsOrchestrator {
3288
2633
  this.emitChange();
3289
2634
  log.info(`Variant ${args.variantId} (${input.briefLabel}) committed by user`);
3290
2635
  if (!args.skipTeardown) {
3291
- // Once a variant is committed, the unpicked worktrees are no longer
3292
- // useful. Schedule teardown in the background so the agent's
3293
- // commit_variant call returns immediately.
3294
2636
  void this.teardownSession(args.sessionId, 'committed').catch((err) => {
3295
2637
  log.warn(`teardownSession after commit failed for ${args.sessionId}`, err);
3296
2638
  });
@@ -3311,25 +2653,7 @@ class AgentVariantsOrchestrator {
3311
2653
  async cleanupCommittedSession(sessionId) {
3312
2654
  await this.teardownSession(sessionId, 'committed');
3313
2655
  }
3314
- /**
3315
- * Ensure the user-facing destination path can receive the new project.
3316
- * Rejects when the path exists and is non-empty.
3317
- *
3318
- * `.rivet/` (pre-commit snapshots + history manifests) and `.gitignore`
3319
- * (written by VariantHistoryService.ensureGitignore when variants persist
3320
- * at success time) are both tolerated — neither is user-authored content
3321
- * that would be clobbered by the materialize step.
3322
- */
3323
- assertDestinationAvailable(destinationPath,
3324
- /**
3325
- * Top-level entries the caller knows it owns and can safely overwrite.
3326
- * Used by the fresh static_preview commit path so a directory holding
3327
- * only this session's per-variant `assetBase` subdirs still counts as
3328
- * "available" — those came from the agent during generation. Any entry
3329
- * NOT in this set (and not the standard `.rivet`/`.gitignore` exemptions)
3330
- * still triggers DESTINATION_NOT_EMPTY.
3331
- */
3332
- additionalAllowedEntries = new Set()) {
2656
+ assertDestinationAvailable(destinationPath, additionalAllowedEntries = new Set()) {
3333
2657
  if (!fs_1.default.existsSync(destinationPath))
3334
2658
  return;
3335
2659
  const entries = fs_1.default.readdirSync(destinationPath);
@@ -3340,18 +2664,13 @@ class AgentVariantsOrchestrator {
3340
2664
  return;
3341
2665
  throw new errors_1.AgentVariantsError('DESTINATION_NOT_EMPTY', `Destination ${destinationPath} is not empty (${userVisibleEntries.length} entries) — refuse to materialize.`);
3342
2666
  }
3343
- /** Read the captured diff for a code-gen variant, if available. */
3344
2667
  getVariantDiff(sessionId, variantId) {
3345
2668
  return this.resources.get(sessionId)?.worktrees.get(variantId)?.diff;
3346
2669
  }
3347
- // --- Side-effect implementations ----------------------------------------
3348
2670
  async provisionWorktrees(sessionId, approveResult) {
3349
2671
  const projectContext = this.store.getProjectContext(sessionId);
3350
2672
  const variantCount = approveResult.codeGenWorkItemIds.length +
3351
2673
  (approveResult.scaffoldBaseWorkItemId ? 1 : 0);
3352
- // Generated + static_preview provisions nothing (HTML is the deliverable)
3353
- // — skip the timing/telemetry wrapper so the fast path stays untouched.
3354
- // `provision: 'none'` is exactly the no-scaffold generated-static lane.
3355
2674
  if ((0, runPlan_1.resolveRunPlanPolicy)(projectContext).provision === 'none') {
3356
2675
  return;
3357
2676
  }
@@ -3364,10 +2683,6 @@ class AgentVariantsOrchestrator {
3364
2683
  });
3365
2684
  const run = async () => {
3366
2685
  if (projectContext.kind === 'fresh') {
3367
- // Fresh + vite_app: provision a Vite skeleton per variant and copy the
3368
- // agent-planned assetPlan files before the agent leases its code_gen
3369
- // items. (Background `npm install` is dispatched inside and is NOT
3370
- // awaited here — the timeout bounds worktree creation, not install.)
3371
2686
  await this.provisionFreshWorktrees(sessionId, approveResult, projectContext);
3372
2687
  return;
3373
2688
  }
@@ -3398,9 +2713,6 @@ class AgentVariantsOrchestrator {
3398
2713
  ? err.code
3399
2714
  : 'PROVISION_FAILED',
3400
2715
  });
3401
- // Cancel synchronously before cleanup so a retry does not see this
3402
- // failed session as active. cancel() schedules teardown without blocking
3403
- // the provisioning error on git cleanup.
3404
2716
  void this.cancel({ sessionId, reason: 'provisioning_failed' }).catch((teardownErr) => {
3405
2717
  log.warn(`cleanup after provisioning failure for ${sessionId} failed`, teardownErr);
3406
2718
  });
@@ -3415,10 +2727,6 @@ class AgentVariantsOrchestrator {
3415
2727
  throw err;
3416
2728
  }
3417
2729
  }
3418
- /**
3419
- * Existing-project flow: clone the user's repo N times via git worktree.
3420
- * Waits for source and dependency copies before making work available.
3421
- */
3422
2730
  async provisionExistingWorktrees(sessionId, approveResult) {
3423
2731
  const resources = this.ensureResources(sessionId);
3424
2732
  const totalCount = approveResult.codeGenWorkItemIds.length +
@@ -3445,19 +2753,6 @@ class AgentVariantsOrchestrator {
3445
2753
  });
3446
2754
  }
3447
2755
  }
3448
- /**
3449
- * Fresh-project flow: scaffold one template per variant + DESIGN.md per
3450
- * slot synchronously (fast — just file writes + git init), then dispatch a
3451
- * background `npm install` task per worktree. Returns immediately so the
3452
- * `approve_variant_briefs` MCP tool doesn't time out on cold installs.
3453
- *
3454
- * On install success: `sessionStore.completeInternal(scaffold_base)` runs,
3455
- * which unblocks the dependent code_gen items.
3456
- *
3457
- * On install failure: the scaffold_base work item is marked failed via
3458
- * `failInternal`, which cascades DEPENDENCY_FAILED to all dependent
3459
- * code_gen items so the session degrades cleanly.
3460
- */
3461
2756
  async provisionFreshWorktrees(sessionId, approveResult, projectContext) {
3462
2757
  const resources = this.ensureResources(sessionId);
3463
2758
  const scaffoldId = approveResult.scaffoldBaseWorkItemId;
@@ -3484,33 +2779,14 @@ class AgentVariantsOrchestrator {
3484
2779
  designContext: summarizeDesignContext(designContext),
3485
2780
  });
3486
2781
  log.info(`Provisioning ${codeGenIds.length} fresh worktree(s) for session ${sessionId}`);
3487
- // destinationParent for fresh worktrees: the user's workspace root
3488
- // (sibling to `.rivet/`). Keeping the worktree on the same volume as
3489
- // the materialize destination turns commit into a directory rename
3490
- // instead of a recursive copy. `path.dirname(workspacePath)` *used*
3491
- // to equal `workspaceRoot`, but after nesting subprojects under
3492
- // `<workspaceRoot>/.rivet/<slug>/` the dirname is now `.rivet/`,
3493
- // which would stage worktrees inside `.rivet/.rivet-variants/`.
3494
- // Use workspaceRoot directly so staging lives at
3495
- // `<workspaceRoot>/.rivet-variants/` as originally intended.
3496
2782
  const destinationParent = projectContext.workspaceRoot;
3497
2783
  const paths = await createFresh.call(this.worktrees, sessionId, codeGenIds.length, viteReactTs_1.VITE_REACT_TS_TEMPLATE, designContext, destinationParent);
3498
2784
  resources.scaffoldBaseWorkItemId = scaffoldId;
3499
2785
  resources.freshDestinationParent = destinationParent;
3500
- // Each code_gen item maps 1:1 to a fresh worktree. The scaffold_base
3501
- // work item is internal — no dedicated worktree.
3502
2786
  await Promise.all(codeGenIds.map((workItemId, index) => this.registerWorktreeWorkspace(resources, {
3503
2787
  workItemId,
3504
2788
  worktreePath: paths[index],
3505
2789
  })));
3506
- // Copy agent-planned assets (e.g. avatar.glb) into each worktree so
3507
- // generated code can reference them via plan.referenceAs. Done before
3508
- // the background install so the assets are on disk by the time the
3509
- // agent leases its code_gen item.
3510
- // If copy throws (e.g. source asset deleted between planning and
3511
- // provisioning), fail scaffold_base immediately so dependent code_gen
3512
- // items cascade DEPENDENCY_FAILED instead of leaving the session
3513
- // permanently stuck in `work_items_ready`.
3514
2790
  const assetPlan = projectContext.executionPlan?.assetPlan ?? [];
3515
2791
  if (assetPlan.length > 0) {
3516
2792
  try {
@@ -3542,18 +2818,10 @@ class AgentVariantsOrchestrator {
3542
2818
  return;
3543
2819
  }
3544
2820
  }
3545
- // Background install: don't await. The orchestrator finishes the
3546
- // approve→provision call immediately; the agent polls for scaffold
3547
- // completion via continue_variants(action='check').
3548
2821
  void this.runBackgroundInstall(sessionId, scaffoldId, paths, scaffoldStartedAt).catch((err) => {
3549
2822
  log.error(`runBackgroundInstall failed for session ${sessionId}`, err);
3550
2823
  });
3551
2824
  }
3552
- /**
3553
- * Run `npm install` in parallel across all fresh worktrees. On all-success,
3554
- * mark scaffold_base succeeded via `completeInternal`. On any failure,
3555
- * mark scaffold_base failed via `failInternal` and emit telemetry.
3556
- */
3557
2825
  async runBackgroundInstall(sessionId, scaffoldWorkItemId, worktreePaths, scaffoldStartedAt) {
3558
2826
  const installStartedAt = Date.now();
3559
2827
  try {
@@ -3563,8 +2831,6 @@ class AgentVariantsOrchestrator {
3563
2831
  })));
3564
2832
  }
3565
2833
  catch (err) {
3566
- // Teardown aborts in-flight preparation; a cancelled session is not a
3567
- // scaffold failure.
3568
2834
  const resources = this.resources.get(sessionId);
3569
2835
  if (!resources || resources.cleanupStarted)
3570
2836
  return;
@@ -3606,12 +2872,6 @@ class AgentVariantsOrchestrator {
3606
2872
  variantCount: worktreePaths.length,
3607
2873
  });
3608
2874
  }
3609
- /**
3610
- * Checks succeeded implementation reports before they reach the store.
3611
- * Static previews must contain a structurally complete local artifact;
3612
- * applicable existing-project variants must contain an added diff. Returns
3613
- * a pass, a single repair retry, or a terminal integrity failure.
3614
- */
3615
2875
  async evaluateQaForReport(args) {
3616
2876
  if (args.status !== 'succeeded')
3617
2877
  return null;
@@ -3619,15 +2879,12 @@ class AgentVariantsOrchestrator {
3619
2879
  return null;
3620
2880
  const projectContext = this.store.getProjectContext(args.sessionId);
3621
2881
  const kind = this.store.getWorkItemKind(args.sessionId, args.workItemId);
3622
- // Existing-project code_gen has no owned preview document to inspect. Its
3623
- // structural contract is a captured diff containing added source content.
3624
2882
  if (projectContext.kind !== 'fresh') {
3625
2883
  if (kind === 'code_gen') {
3626
2884
  return this.evaluateExistingCodeGenQa(args);
3627
2885
  }
3628
2886
  return null;
3629
2887
  }
3630
- // Resolve the objective base QA for this deliverable kind.
3631
2888
  let baseQa = null;
3632
2889
  const checkedSource = undefined;
3633
2890
  if (kind === 'static_preview') {
@@ -3637,8 +2894,6 @@ class AgentVariantsOrchestrator {
3637
2894
  baseQa = await this.runPreviewQaSafely(args, parsed.html);
3638
2895
  }
3639
2896
  else if (kind === 'code_gen') {
3640
- // Fresh vite_app variants run agent-authored dev-server code. No
3641
- // preview document to inspect — behave exactly as before.
3642
2897
  return null;
3643
2898
  }
3644
2899
  else {
@@ -3656,7 +2911,6 @@ class AgentVariantsOrchestrator {
3656
2911
  },
3657
2912
  };
3658
2913
  }
3659
- // Synthesize a passing base verdict for vite_app (no objective layer).
3660
2914
  const passedBase = baseQa ?? {
3661
2915
  status: 'passed',
3662
2916
  issues: [],
@@ -3740,8 +2994,6 @@ class AgentVariantsOrchestrator {
3740
2994
  },
3741
2995
  };
3742
2996
  }
3743
- /** Run the injected preview QA runner, converting a thrown runner into a
3744
- * failed `VariantQaResult` (mirrors the prior inline behavior). */
3745
2997
  async runPreviewQaSafely(args, html) {
3746
2998
  try {
3747
2999
  return await this.previewQaRunner({
@@ -3768,11 +3020,6 @@ class AgentVariantsOrchestrator {
3768
3020
  memoizeQa(sessionId, workItemId, qa) {
3769
3021
  this.ensureResources(sessionId).qaResults.set(workItemId, qa);
3770
3022
  }
3771
- /**
3772
- * Handle a `retry` QA verdict: consume the agent's report, re-open the
3773
- * variant work item so it can be re-leased and regenerated against the QA
3774
- * notes, and record that it has now used its single retry.
3775
- */
3776
3023
  async handleQaRegenRetry(args, qa) {
3777
3024
  const resources = this.ensureResources(args.sessionId);
3778
3025
  const result = this.store.requeueForRegeneration({
@@ -3794,11 +3041,6 @@ class AgentVariantsOrchestrator {
3794
3041
  overall: null,
3795
3042
  });
3796
3043
  this.emitChange();
3797
- // Carry the requeue signal + critique so the tool layer can tell the agent
3798
- // to re-lease and regenerate. The store result is an opaque
3799
- // `waiting_for_results` (the variant is pending again); on its own that is
3800
- // indistinguishable from a sibling still in flight, so the agent would
3801
- // otherwise abandon the variant and the session would stall at ready:0.
3802
3044
  const completionResult = { ...result, requeuedForRegeneration: true, qa };
3803
3045
  resources.repairCompletionResults.set(repairCompletionKey(args), completionResult);
3804
3046
  return completionResult;
@@ -3817,16 +3059,6 @@ class AgentVariantsOrchestrator {
3817
3059
  args.record.pendingAutoRestart !== args.autoRestartTimer;
3818
3060
  return Boolean(resources && !resources.cleanupStarted && !isAutoRestartCancelled);
3819
3061
  };
3820
- // Bring up a dev server in the variant's worktree so the user can cycle
3821
- // through live variants in the iframe via the chip. Failures here are
3822
- // logged but non-fatal — the user can still pick by reading the diff.
3823
- //
3824
- // Pick a sensible port near the framework's default (3000 for Next, 5173
3825
- // for Vite) and inject it via PORT + the CLI flag (see buildDevServerCommand)
3826
- // so the server actually binds it — that's what moves a preview off a port
3827
- // the user's own dev server already holds instead of colliding on it. On a
3828
- // retry we scan past the port we just tried, so a transient race or a
3829
- // briefly-held port resolves onto the next free one.
3830
3062
  const previewStartedAt = Date.now();
3831
3063
  const projectContextKind = args.isFresh ? 'fresh' : 'existing';
3832
3064
  trackPreviewStarted(this.telemetry, {
@@ -3838,13 +3070,9 @@ class AgentVariantsOrchestrator {
3838
3070
  const startPort = await this.resolveDevServerStartPort(args.sessionId, args.isFresh);
3839
3071
  let scanFrom = startPort;
3840
3072
  const maxAttempts = DEV_SERVER_START_MAX_ATTEMPTS;
3841
- // At most one install-then-retry per start: a second missing-module exit
3842
- // after a fresh install means the install can't fix it.
3843
3073
  let installRetried = false;
3844
3074
  let lastDev;
3845
3075
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
3846
- // Teardown can begin while a prior attempt waits for dependency
3847
- // installation. Do not start more work against a removed worktree.
3848
3076
  if (!canContinueStart())
3849
3077
  return undefined;
3850
3078
  let port;
@@ -3855,10 +3083,6 @@ class AgentVariantsOrchestrator {
3855
3083
  if (!canContinueStart())
3856
3084
  return undefined;
3857
3085
  const proc = await this.worktrees.startDevServer(dev.cwd, port, dev.cmd, dev.args, dev.env);
3858
- // The boot can outlive the session (a cancel during the readiness
3859
- // wait, or during an auto-restart's delay). At this point the child
3860
- // isn't on the record yet, so teardown's stop loop can't see it —
3861
- // kill it here instead of leaking an orphaned dev server.
3862
3086
  if (!canContinueStart()) {
3863
3087
  log.info(`Variant ${args.workItemId} dev server booted after preview cleanup; stopping it`);
3864
3088
  void this.worktrees.stopDevServer(proc).catch(() => undefined);
@@ -3870,16 +3094,6 @@ class AgentVariantsOrchestrator {
3870
3094
  args.record.port = port;
3871
3095
  args.record.devServerProcess = proc;
3872
3096
  args.record.devCommand = dev;
3873
- // If the dev server dies on its own (crash, OOM, Vite hard-fail),
3874
- // clear the port so the iframe stops routing the chip onto a dead
3875
- // socket, then bring a replacement up automatically. A ready server
3876
- // that later crashes is almost always recoverable by a clean restart
3877
- // (transient OOM, watcher crash, HMR wedge) — without one, every such
3878
- // crash surfaced as a permanent "preview unavailable" plus a burst of
3879
- // upstream_lost noise until the user regenerated the variant. The
3880
- // restart budget keeps a genuinely broken build (crash loop) from
3881
- // restarting forever. Intentional stops clear `devServerProcess`
3882
- // before killing, so the guard below filters them out.
3883
3097
  proc.once('exit', (code, signal) => {
3884
3098
  if (args.record.devServerProcess !== proc)
3885
3099
  return;
@@ -3898,8 +3112,6 @@ class AgentVariantsOrchestrator {
3898
3112
  args.record.devServerAutoRestarts = restartsUsed + 1;
3899
3113
  this.emitChange();
3900
3114
  const timer = setTimeout(() => {
3901
- // Re-check: the session may have been torn down while the
3902
- // restart was pending — don't spawn into a cleaned-up worktree.
3903
3115
  const current = this.resources.get(args.sessionId);
3904
3116
  if (!current ||
3905
3117
  current.cleanupStarted ||
@@ -3927,8 +3139,6 @@ class AgentVariantsOrchestrator {
3927
3139
  });
3928
3140
  this.emitChange();
3929
3141
  });
3930
- // A prior failure record (startup failure before a successful retry,
3931
- // idle reclaim, crash before this restart) is now stale.
3932
3142
  this.resources
3933
3143
  .get(args.sessionId)
3934
3144
  ?.previewFailures.delete(args.workItemId);
@@ -3957,16 +3167,6 @@ class AgentVariantsOrchestrator {
3957
3167
  const devErr = (0, devServerError_1.isDevServerStartError)(err) ? err : undefined;
3958
3168
  const portInUse = devErr?.portInUse ?? false;
3959
3169
  const reason = devErr?.reason ?? 'unknown';
3960
- // Classify what a retry can actually fix:
3961
- // - port_in_use: a fresh port fixes it (also step past unmatched
3962
- // collision messages via the blanket exited retry below).
3963
- // - missing/stale dependencies (module-resolution errors in the
3964
- // output): an install fixes it — install, then retry once.
3965
- // - any other early exit: retry once; exits fail fast, so one clean
3966
- // attempt is cheap insurance against transient races (fs churn from
3967
- // sibling provisioning, npm cache contention).
3968
- // - timeout / spawn_error / missing_dev_script: deterministic; a
3969
- // retry just doubles the wait, so fail with the actionable cause.
3970
3170
  const missingDepsOutput = (0, devServerError_1.isMissingDependencyOutput)(devErr?.detail ?? '');
3971
3171
  const missingDeps = missingDepsOutput &&
3972
3172
  reason === 'exited' &&
@@ -3975,8 +3175,6 @@ class AgentVariantsOrchestrator {
3975
3175
  canInstallWithoutTouchingHost(lastDev.cwd);
3976
3176
  const willRetry = attempt < maxAttempts &&
3977
3177
  (portInUse || missingDeps || (reason === 'exited' && attempt === 1));
3978
- // Next attempt scans past the port we just tried so we don't re-pick a
3979
- // port that's persistently held (vs. a transient race that freed it).
3980
3178
  scanFrom = (port ?? scanFrom) + 1;
3981
3179
  log.warn(`Failed to start dev server for variant ${args.workItemId} on port ${port ?? 'unallocated'} ` +
3982
3180
  `(attempt ${attempt}/${maxAttempts}, reason=${reason}, portInUse=${portInUse}, missingDeps=${missingDeps})` +
@@ -4020,9 +3218,6 @@ class AgentVariantsOrchestrator {
4020
3218
  }
4021
3219
  continue;
4022
3220
  }
4023
- // Record the failure so getVariants can tell the UI this direction's
4024
- // preview couldn't start (and why), then push a snapshot so the chip
4025
- // updates from "loading" to the accurate per-direction message.
4026
3221
  this.resources
4027
3222
  .get(args.sessionId)
4028
3223
  ?.previewFailures.set(args.workItemId, {
@@ -4034,10 +3229,6 @@ class AgentVariantsOrchestrator {
4034
3229
  errorCode = 'DEPENDENCY_INSTALL_FAILED';
4035
3230
  if (reason === 'missing_dev_script')
4036
3231
  errorCode = 'DEV_SCRIPT_MISSING';
4037
- // Telemetry gets structured classification only — never the raw
4038
- // output tail, which routinely carries absolute project paths and
4039
- // source frames (see AGENTS.md "What NEVER to capture"). The full
4040
- // tail still reaches the local logs via `err` above.
4041
3232
  trackFreshDevServerFailed(this.telemetry, {
4042
3233
  sessionId: args.sessionId,
4043
3234
  variantId: args.workItemId,
@@ -4065,9 +3256,6 @@ class AgentVariantsOrchestrator {
4065
3256
  return undefined;
4066
3257
  }
4067
3258
  finally {
4068
- // Hand the reservation back whether the dev server bound the port
4069
- // (now visible to the listener check, so the reservation is redundant),
4070
- // it failed (port free again), or we're about to retry on the next port.
4071
3259
  if (port !== undefined)
4072
3260
  this.worktrees.releasePort?.(port);
4073
3261
  }
@@ -4095,12 +3283,6 @@ class AgentVariantsOrchestrator {
4095
3283
  assetBase: staticPreview.assetBase,
4096
3284
  projectContext,
4097
3285
  });
4098
- // Materialize the variant into a per-variant directory so every
4099
- // static variant is directory-backed (the same shape as the
4100
- // worktree-based variants). Reuse the agent's assetBase dir when it
4101
- // wrote sibling assets; otherwise create a Rivet-managed per-variant
4102
- // dir under workspacePath. `staticPreview.html` is the complete built
4103
- // document (html + css + js), written as index.html.
4104
3286
  const workspacePath = projectContext.kind === 'fresh'
4105
3287
  ? projectContext.workspacePath
4106
3288
  : undefined;
@@ -4123,16 +3305,10 @@ class AgentVariantsOrchestrator {
4123
3305
  }
4124
3306
  try {
4125
3307
  fs_1.default.mkdirSync(dir, { recursive: true });
4126
- // Realpath the dir so it lines up with the realpath'd destination
4127
- // the commit emptiness-check compares against (macOS symlinks
4128
- // `/var` → `/private/var`). `resolveStaticPreviewAssetBase`
4129
- // already realpaths the agent-provided case; do the same for the
4130
- // Rivet-created dir.
4131
3308
  try {
4132
3309
  dir = fs_1.default.realpathSync(dir);
4133
3310
  }
4134
3311
  catch {
4135
- // keep the un-realpath'd path if realpath fails
4136
3312
  }
4137
3313
  fs_1.default.writeFileSync(path_1.default.join(dir, 'index.html'), staticPreview.html, 'utf8');
4138
3314
  }
@@ -4153,8 +3329,6 @@ class AgentVariantsOrchestrator {
4153
3329
  resources.workspaceManager.removeArtifactWorkspace(workItemId);
4154
3330
  }
4155
3331
  if (this.store.getProjectContext(sessionId).kind === 'fresh') {
4156
- // History at `<workspacePath>/.rivet/variants/<sessionId>/<variantId>/`
4157
- // is the on-disk record for this generated project.
4158
3332
  this.trackHistoryPersist(this.persistCompletedFreshVariant({
4159
3333
  sessionId,
4160
3334
  workItemId,
@@ -4185,8 +3359,6 @@ class AgentVariantsOrchestrator {
4185
3359
  log.warn(`No worktree record for ${sessionId}/${workItemId}; skipping diff capture`);
4186
3360
  return;
4187
3361
  }
4188
- // scaffold_base sets up the base for dependent code_gen items. No diff
4189
- // to capture from it — its result is the disk state of the worktree.
4190
3362
  if (resources.scaffoldBaseWorkItemId === workItemId) {
4191
3363
  log.info(`scaffold_base ${workItemId} succeeded; awaiting dependent code-gen`);
4192
3364
  return;
@@ -4202,14 +3374,6 @@ class AgentVariantsOrchestrator {
4202
3374
  catch (err) {
4203
3375
  log.warn(`getDiff failed for ${record.worktreePath}`, err);
4204
3376
  }
4205
- // History: persist every completed variant immediately to
4206
- // `<projectPath>/.rivet/variants/`. Existing projects pass the captured
4207
- // diff (or an empty string when capture itself failed — the variant
4208
- // still succeeded code-gen-wise, and the history row is the only
4209
- // record the UI has). Fresh-project variants copy their worktree
4210
- // (vite_app) or the staged HTML (static_preview). Best-effort — a
4211
- // failure here must never block dev-server startup or the user's pick
4212
- // flow.
4213
3377
  if (!isFresh) {
4214
3378
  this.trackHistoryPersist(this.persistCompletedExistingVariant({
4215
3379
  sessionId,
@@ -4227,19 +3391,8 @@ class AgentVariantsOrchestrator {
4227
3391
  log.warn(`persistCompletedFreshVariant failed for ${sessionId}/${workItemId}`, err);
4228
3392
  }));
4229
3393
  }
4230
- // Static existing-mode projects (framework='static', no dev command) have
4231
- // no per-variant dev server to proxy the iframe at. Serve the variant's
4232
- // materialized static files directly — the same renderer the chip/iframe
4233
- // already uses for fresh static_preview variants — so the variant is
4234
- // viewable/cyclable instead of being silently stuck on "Preview is
4235
- // unavailable for this variant". When this succeeds there is no dev server
4236
- // to bring up, so skip the proxy path below.
4237
3394
  if (!isFresh) {
4238
3395
  const staticPreview = await this.registerExistingStaticPreview(sessionId, workItemId, record);
4239
- // Existing projects resolve their preview surface at success time (the
4240
- // one genuinely-late axis of the run plan): a framework='static' project
4241
- // materializes static files → static_artifact and needs no dev server;
4242
- // anything else falls through to the dev-server proxy below.
4243
3396
  if (staticPreview !== 'not_static') {
4244
3397
  this.emitChange();
4245
3398
  return;
@@ -4273,17 +3426,8 @@ class AgentVariantsOrchestrator {
4273
3426
  assetBase: parsed.assetBase,
4274
3427
  projectContext: this.store.getProjectContext(args.sessionId),
4275
3428
  });
4276
- // A refinement that only rewrites HTML won't re-declare an assetBase, but
4277
- // the refined markup can still reference the original sibling assets
4278
- // (images, GLB, fonts). Fall back to the variant's existing asset base so
4279
- // those relative URLs keep resolving instead of 404ing after the swap.
4280
3429
  const previousRecord = resources.staticPreviews.get(input.variantId);
4281
3430
  const dir = resolvedAssetBase ?? previousRecord?.assetBase;
4282
- // Re-materialize index.html in the per-variant dir FIRST. The directory is
4283
- // the source of truth (`getStaticPreviewHtml` reads it disk-first), so the
4284
- // write must succeed before we swap any in-memory / stored-output state to
4285
- // the refined HTML. If it fails we throw — converting to a `failed` report
4286
- // rather than a success that still serves the pre-refine document on disk.
4287
3431
  if (dir) {
4288
3432
  try {
4289
3433
  fs_1.default.mkdirSync(dir, { recursive: true });
@@ -4293,9 +3437,6 @@ class AgentVariantsOrchestrator {
4293
3437
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `Failed to materialize refined static preview for ${input.variantId}: ${err instanceof Error ? err.message : String(err)}`);
4294
3438
  }
4295
3439
  }
4296
- // Swap the served preview to the refined HTML. Runs before
4297
- // store.reportComplete so any failure above converts to a `failed` report
4298
- // rather than a success pointing at unrefreshed output.
4299
3440
  this.store.replaceWorkItemOutput(args.sessionId, input.variantId, {
4300
3441
  ...parsed,
4301
3442
  ...(dir ? { assetBase: dir } : {}),
@@ -4317,10 +3458,6 @@ class AgentVariantsOrchestrator {
4317
3458
  targetWorkItemId: input.variantId,
4318
3459
  });
4319
3460
  }
4320
- // History persistence is best-effort, mirroring handleSucceededReport's
4321
- // fire-and-forget persistence for freshly completed variants. A failure
4322
- // here (e.g. a transient filesystem race) must not fail the refinement or
4323
- // discard the already-serving refined HTML.
4324
3461
  try {
4325
3462
  await this.persistCompletedFreshVariant({
4326
3463
  sessionId: args.sessionId,
@@ -4330,22 +3467,10 @@ class AgentVariantsOrchestrator {
4330
3467
  catch (err) {
4331
3468
  log.warn(`persistCompletedFreshVariant failed for refined variant ${input.variantId} (session ${args.sessionId}); preview already swapped`, err);
4332
3469
  }
4333
- // The caller (reportComplete) emits the change after recording success so
4334
- // the snapshot reflects both the swapped HTML and refinement.status.
4335
3470
  }
4336
- /** The worktree/dev-server manager this orchestrator boots previews with.
4337
- * Exposed so HistoryReplayService shares the SAME instance: the
4338
- * reserved-but-not-yet-bound port set is per-instance, and a second
4339
- * manager scanning the same range can hand a live variant's pending port
4340
- * to a replay (EADDRINUSE for the loser). */
4341
3471
  get devServerManager() {
4342
3472
  return this.worktrees;
4343
3473
  }
4344
- /** In-flight fire-and-forget history persists. Tree-store snapshots spawn
4345
- * git subprocesses, so these can outlive the microtask flushes that used
4346
- * to be enough to drain them — {@link teardownSession} (and the test
4347
- * helpers' settleBackgroundWork) await {@link settleHistoryPersists}
4348
- * instead of racing the writes. */
4349
3474
  pendingHistoryPersists = new Set();
4350
3475
  trackHistoryPersist(persist) {
4351
3476
  this.pendingHistoryPersists.add(persist);
@@ -4355,20 +3480,11 @@ class AgentVariantsOrchestrator {
4355
3480
  this.pendingHistoryPersists.delete(persist);
4356
3481
  });
4357
3482
  }
4358
- /** Await every in-flight history persist, including ones that start while
4359
- * draining (a refine can persist mid-settle). */
4360
3483
  async settleHistoryPersists() {
4361
3484
  while (this.pendingHistoryPersists.size > 0) {
4362
3485
  await Promise.allSettled([...this.pendingHistoryPersists]);
4363
3486
  }
4364
3487
  }
4365
- /**
4366
- * Persist a completed existing-project code_gen variant into
4367
- * `<env.projectPath>/.rivet/variants/<sessionId>/<variantId>/`. Called from
4368
- * `handleSucceededReport` once the worktree diff has been captured but
4369
- * before the user picks. Status is `completed` until `commitVariant` or a
4370
- * cancellation transitions it.
4371
- */
4372
3488
  async persistCompletedExistingVariant(args) {
4373
3489
  const projectContext = this.store.getProjectContext(args.sessionId);
4374
3490
  if (projectContext.kind !== 'existing')
@@ -4396,13 +3512,7 @@ class AgentVariantsOrchestrator {
4396
3512
  }
4397
3513
  const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
4398
3514
  const sessionPrompt = this.store.getPrompt(args.sessionId);
4399
- // Tree-store snapshot inputs (dual-write). The snapshot root is the
4400
- // worktree root — the git root, per the tree-root contract — for EVERY
4401
- // framework, not just static: this is what makes dev-server (Vite /
4402
- // fullstack) variants replayable from history instead of diff-only.
4403
3515
  const snapshotDir = record?.worktreePath;
4404
- // Lazy per-session base snapshot from the host repo root. Best-effort:
4405
- // resolution failure just means no base ref (variant commits still land).
4406
3516
  let baseDir;
4407
3517
  try {
4408
3518
  baseDir = await this.worktrees.getGitRoot?.();
@@ -4412,9 +3522,6 @@ class AgentVariantsOrchestrator {
4412
3522
  }
4413
3523
  let serve;
4414
3524
  if (sourceDir && record && staticEntryPath) {
4415
- // Static framework: entryPath is relative to the snapshot root (the
4416
- // worktree root), pointing into the nested project dir when the
4417
- // project lives below the git root.
4418
3525
  const entryPath = path_1.default.relative(record.worktreePath, path_1.default.join(sourceDir, staticEntryPath));
4419
3526
  serve = { kind: 'static', entryPath };
4420
3527
  }
@@ -4425,12 +3532,6 @@ class AgentVariantsOrchestrator {
4425
3532
  };
4426
3533
  }
4427
3534
  else if (record) {
4428
- // Persist fires at code-gen success, BEFORE the dev server boots (the
4429
- // boot is what stashes record.devCommand/port) — so for the common
4430
- // path the live invocation isn't available yet. Run the same
4431
- // deterministic resolution the boot will use, against a sentinel port
4432
- // that becomes the ${PORT} placeholder. No dependency install here —
4433
- // resolveDevServerCommand is the side-effect-free half of the split.
4434
3535
  try {
4435
3536
  const dev = await this.resolveDevServerCommand(args.sessionId, record.worktreePath, RECIPE_PORT_SENTINEL, false);
4436
3537
  serve = {
@@ -4470,22 +3571,6 @@ class AgentVariantsOrchestrator {
4470
3571
  : {}),
4471
3572
  });
4472
3573
  }
4473
- /**
4474
- * Existing-mode `framework: 'static'` projects have no dev command, so there
4475
- * is no per-variant dev server for the iframe to proxy. Register the variant's
4476
- * materialized static site as a {@link StaticPreviewRecord} so the existing
4477
- * static-file plumbing — the `/api/variants/:sid/static/:vid[/asset]` routes,
4478
- * {@link getStaticPreviewHtml}, and {@link getVariants} (preview.kind=
4479
- * 'static_artifact', view enabled) — all light up exactly as they do for
4480
- * fresh `static_preview` variants. The entry HTML and its sibling assets are
4481
- * served straight from the variant's worktree project root (session-scoped,
4482
- * pre-commit; the persisted `.rivet/variants/.../files/` copy backs the
4483
- * post-session history route separately).
4484
- *
4485
- * Returns `registered` when the static preview is ready, `unavailable` when
4486
- * the project is static but its selected entry cannot be served, and
4487
- * `not_static` when the caller should start a dev server instead.
4488
- */
4489
3574
  async registerExistingStaticPreview(sessionId, workItemId, record) {
4490
3575
  let env;
4491
3576
  try {
@@ -4518,9 +3603,6 @@ class AgentVariantsOrchestrator {
4518
3603
  log.warn(`registerExistingStaticPreview: project cwd failed for ${sessionId}/${workItemId}`, err);
4519
3604
  return 'unavailable';
4520
3605
  }
4521
- // The materialized worktree IS the per-variant directory. Require its
4522
- // selected entry to exist; the directory is then served directly (no
4523
- // in-memory HTML copy — getStaticPreviewHtml reads it from here).
4524
3606
  const entryFile = path_1.default.join(projectCwd, env.entryPath);
4525
3607
  try {
4526
3608
  await fs_1.default.promises.access(entryFile, fs_1.default.constants.R_OK);
@@ -4542,41 +3624,26 @@ class AgentVariantsOrchestrator {
4542
3624
  });
4543
3625
  return 'unavailable';
4544
3626
  }
4545
- // The dir must be realpath'd so resolveStaticPreviewAssetPath's sandbox
4546
- // comparison lines up; sibling assets (css/js/images) then resolve from the
4547
- // same static root the entry HTML lives in.
4548
3627
  let dir;
4549
3628
  try {
4550
3629
  dir = fs_1.default.realpathSync(projectCwd);
4551
3630
  }
4552
3631
  catch {
4553
- // Fall back to the un-realpath'd cwd; serving still works, only the
4554
- // sandbox symlink-normalization is skipped.
4555
3632
  dir = projectCwd;
4556
3633
  }
4557
- // Host project root, used as a read-only fallback for assets the worktree
4558
- // clone is missing (git-ignored or binary files that `git worktree add` +
4559
- // text-patch + untracked-copy can't carry). Without this the original
4560
- // preview shows such an asset while the variant 404s. Realpath'd so the
4561
- // sandbox containment check in `resolveAssetWithinBase` lines up.
4562
3634
  let assetFallbackBase;
4563
3635
  try {
4564
3636
  const hostRealRoot = fs_1.default.realpathSync(env.projectPath);
4565
- // Skip the fallback if it would collapse onto the worktree root (can't
4566
- // happen in practice, but keeps the two roots genuinely distinct).
4567
3637
  if (hostRealRoot !== dir)
4568
3638
  assetFallbackBase = hostRealRoot;
4569
3639
  }
4570
3640
  catch {
4571
- // No host root resolvable — serve worktree assets only.
4572
3641
  }
4573
3642
  resources.staticPreviews.set(workItemId, {
4574
3643
  workItemId,
4575
3644
  briefId: input.briefId,
4576
3645
  entryPath: env.entryPath,
4577
3646
  assetBase: dir,
4578
- // Existing-mode static projects are real multi-file sites — assume
4579
- // sibling assets so the preview route resolves relative URLs.
4580
3647
  hasAssets: true,
4581
3648
  ...(assetFallbackBase ? { assetFallbackBase } : {}),
4582
3649
  });
@@ -4592,25 +3659,10 @@ class AgentVariantsOrchestrator {
4592
3659
  });
4593
3660
  return 'registered';
4594
3661
  }
4595
- /**
4596
- * Persist a completed fresh-project variant into
4597
- * `<projectContext.workspacePath>/.rivet/variants/<sessionId>/<variantId>/`.
4598
- * Called from `handleSucceededReport` right after the per-variant snapshot
4599
- * lands on disk — for static_preview that's the `.rivet/<slug>/` snapshot
4600
- * dir; for vite_app fresh variants it's the worktree itself. Status starts
4601
- * as 'completed' and transitions to 'committed' / 'rejected' / 'cancelled'
4602
- * via `markStatus` at commit or teardown time.
4603
- *
4604
- * Running at success time (rather than commit time) means the history panel
4605
- * populates live as variants generate — including when the user never picks
4606
- * one. Mirrors the existing-project persistCompletedExistingVariant flow.
4607
- */
4608
3662
  async persistCompletedFreshVariant(args) {
4609
3663
  const projectContext = this.store.getProjectContext(args.sessionId);
4610
3664
  if (projectContext.kind !== 'fresh')
4611
3665
  return;
4612
- // Variant history lives in the generated project folder so reopening that
4613
- // folder gives the history panel the same owner path that wrote it.
4614
3666
  const historyProjectPath = projectContext.workspacePath;
4615
3667
  const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
4616
3668
  const sessionPrompt = this.store.getPrompt(args.sessionId);
@@ -4618,11 +3670,6 @@ class AgentVariantsOrchestrator {
4618
3670
  const resources = this.resources.get(args.sessionId);
4619
3671
  const worktreeRecord = resources?.worktrees.get(args.workItemId);
4620
3672
  const staticPreview = resources?.staticPreviews.get(args.workItemId);
4621
- // Vite_app deliverables are full scaffolded worktrees — pass the worktree
4622
- // directory as sourceDir and let copyDirFiltered handle it (excludes
4623
- // node_modules, .rivet, etc). Static_preview deliverables are inline HTML
4624
- // captured in `resources.staticPreviews`; stage them in a tmp dir so the
4625
- // existing copy path works without poking the user's workspace.
4626
3673
  let sourceDir = null;
4627
3674
  let tmpStagingDir = null;
4628
3675
  if (worktreeRecord && fs_1.default.existsSync(worktreeRecord.worktreePath)) {
@@ -4631,7 +3678,6 @@ class AgentVariantsOrchestrator {
4631
3678
  else if (staticPreview) {
4632
3679
  tmpStagingDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `rivet-variant-${args.workItemId}-`));
4633
3680
  copyStaticPreviewDirectory(staticPreview.assetBase, tmpStagingDir);
4634
- // Read the materialized index.html from the variant's per-variant dir.
4635
3681
  let stagedHtml = '';
4636
3682
  try {
4637
3683
  stagedHtml = fs_1.default.readFileSync(path_1.default.join(staticPreview.assetBase, 'index.html'), 'utf8');
@@ -4647,10 +3693,6 @@ class AgentVariantsOrchestrator {
4647
3693
  log.warn(`persistCompletedFreshVariant: no source for ${args.workItemId} (session ${args.sessionId}); skipping`);
4648
3694
  return;
4649
3695
  }
4650
- // For static_preview, only `index.html` is a real deliverable — `brief.md`
4651
- // is implementation-detail staging that we copy alongside it. Hardcode
4652
- // the count so the history row matches what `commit_variant` reports
4653
- // (always 1) instead of double-counting the brief.
4654
3696
  const changedFilesCount = staticPreview ? 1 : countWorktreeFiles(sourceDir);
4655
3697
  const preview = staticPreview
4656
3698
  ? { kind: 'static', entryPath: 'index.html' }
@@ -4662,12 +3704,6 @@ class AgentVariantsOrchestrator {
4662
3704
  script: 'dev',
4663
3705
  },
4664
3706
  };
4665
- // Tree-store serve contract. Fresh worktrees prefer the live record's
4666
- // resolved invocation (stashed at dev-server start); the fallback recipe
4667
- // mirrors resolveDevServer's fresh branch, which is fully deterministic
4668
- // for the Vite template. Static previews serve their staged index.html.
4669
- // Fresh sessions have no host project, so there is no base snapshot —
4670
- // variant commits are root commits.
4671
3707
  const serve = staticPreview
4672
3708
  ? { kind: 'static', entryPath: 'index.html' }
4673
3709
  : worktreeRecord?.devCommand && worktreeRecord.port !== undefined
@@ -4730,10 +3766,6 @@ class AgentVariantsOrchestrator {
4730
3766
  }
4731
3767
  }
4732
3768
  }
4733
- /**
4734
- * @effect Drains fresh-project history writes before commit moves or rewrites
4735
- * the generated project folder.
4736
- */
4737
3769
  async persistCompletedFreshVariantsForCommit(sessionId) {
4738
3770
  const projectContext = this.store.getProjectContext(sessionId);
4739
3771
  if (projectContext.kind !== 'fresh')
@@ -4753,14 +3785,6 @@ class AgentVariantsOrchestrator {
4753
3785
  }
4754
3786
  }
4755
3787
  }
4756
- /**
4757
- * At commit time, flip persisted variant manifests to terminal statuses
4758
- * ('committed' for the chosen, 'rejected' for the rest). Both existing- and
4759
- * fresh-project variants have already been persisted at code_gen success
4760
- * time, so this is a pure status update — no source-dir copy required.
4761
- * Also records the destination path on the chosen variant so history can
4762
- * surface "this variant became <path>".
4763
- */
4764
3788
  async persistVariantHistoryAtCommit(args) {
4765
3789
  const variants = this.store.getVariants(args.sessionId);
4766
3790
  for (const variant of variants) {
@@ -4781,13 +3805,6 @@ class AgentVariantsOrchestrator {
4781
3805
  });
4782
3806
  }
4783
3807
  }
4784
- /**
4785
- * Flip persisted variant manifests to status='cancelled' for every variant
4786
- * in the session that was already snapshotted to disk. Fresh- and existing-
4787
- * project variants both persist at success time now, so both need their
4788
- * manifests flipped here. Best-effort — missing manifests are silently
4789
- * skipped by VariantHistoryService.markStatus.
4790
- */
4791
3808
  async markPersistedVariantsCancelled(sessionId) {
4792
3809
  if (!this.store.hasSession(sessionId))
4793
3810
  return;
@@ -4823,9 +3840,6 @@ class AgentVariantsOrchestrator {
4823
3840
  const projectPath = await this.resolveHistoryProjectPath(sessionId);
4824
3841
  if (!projectPath)
4825
3842
  return;
4826
- // No-ops (ENOENT) when the variant was never persisted — e.g. removing a
4827
- // still-pending variant that produced no artifact. Completed variants have
4828
- // a manifest, which flips to `removed` and is retained on disk.
4829
3843
  await this.variantHistory.markStatus({
4830
3844
  projectPath,
4831
3845
  sessionId,
@@ -4839,9 +3853,6 @@ class AgentVariantsOrchestrator {
4839
3853
  const projectPath = await this.resolveHistoryProjectPath(sessionId);
4840
3854
  if (!projectPath)
4841
3855
  return;
4842
- // No-ops (ENOENT) when the variant has no manifest yet — e.g. renaming a
4843
- // still-generating direction before its artifact lands. The in-memory
4844
- // label still updates; the disk copy catches up when the variant persists.
4845
3856
  await this.variantHistory.renameVariant({
4846
3857
  projectPath,
4847
3858
  sessionId,
@@ -4850,11 +3861,6 @@ class AgentVariantsOrchestrator {
4850
3861
  runLabel,
4851
3862
  });
4852
3863
  }
4853
- /**
4854
- * Resolve the project path that owns `.rivet/variants/` for a session.
4855
- * Existing sessions use the user's project. Fresh sessions use the generated
4856
- * project folder. Must match what `persistCompletedFreshVariant` writes to.
4857
- */
4858
3864
  async resolveHistoryProjectPath(sessionId) {
4859
3865
  const projectContext = this.store.getProjectContext(sessionId);
4860
3866
  if (projectContext.kind === 'fresh') {
@@ -4881,13 +3887,6 @@ class AgentVariantsOrchestrator {
4881
3887
  return undefined;
4882
3888
  }
4883
3889
  }
4884
- /**
4885
- * The port to start scanning from when allocating a variant's preview dev
4886
- * server. Fresh worktrees run the Vite template (5173); existing projects use
4887
- * their detected framework's default (3000 for Next, etc.), falling back to
4888
- * 3000 if detection fails. Scanning upward from here lands the preview on a
4889
- * sensible, predictable port near the project's normal one.
4890
- */
4891
3890
  async resolveDevServerStartPort(sessionId, isFresh) {
4892
3891
  if (isFresh)
4893
3892
  return FRESH_DEV_SERVER_DEFAULT_PORT;
@@ -4899,11 +3898,6 @@ class AgentVariantsOrchestrator {
4899
3898
  return 3000;
4900
3899
  }
4901
3900
  }
4902
- /**
4903
- * Resolve dev server invocation for a worktree. Fresh-project worktrees
4904
- * always use the Vite template's npm command at the worktree root; existing
4905
- * projects defer to the user's framework/packageManager config.
4906
- */
4907
3901
  async resolveDevServer(sessionId, worktreePath, port, isFresh) {
4908
3902
  const resolved = await this.resolveDevServerCommand(sessionId, worktreePath, port, isFresh);
4909
3903
  await this.ensureProjectDependencies({
@@ -4913,13 +3907,6 @@ class AgentVariantsOrchestrator {
4913
3907
  });
4914
3908
  return resolved;
4915
3909
  }
4916
- /**
4917
- * Pure invocation resolution — no dependency installs, no side effects.
4918
- * Split from {@link resolveDevServer} so history persistence can capture
4919
- * the SAME deterministic resolution the boot path uses without booting:
4920
- * persist fires at code-gen success, before the dev server starts, so the
4921
- * live record's stashed command usually isn't available yet.
4922
- */
4923
3910
  async resolveDevServerCommand(sessionId, worktreePath, port, isFresh) {
4924
3911
  if (isFresh) {
4925
3912
  return {
@@ -4943,9 +3930,6 @@ class AgentVariantsOrchestrator {
4943
3930
  throw new Error('Static projects do not have a dev server command');
4944
3931
  }
4945
3932
  const cwd = await this.resolveExistingProjectCwd(sessionId, worktreePath, env);
4946
- // Every branch below — including the production buildDevCommand recipes
4947
- // from utils/devServerCommand.ts — invokes the package.json script named
4948
- // by env.devCommand, so the preflight applies to all of them.
4949
3933
  if (env.devCommand) {
4950
3934
  assertDevScriptExists(cwd, env.devCommand);
4951
3935
  }
@@ -4981,7 +3965,6 @@ class AgentVariantsOrchestrator {
4981
3965
  packageManager,
4982
3966
  };
4983
3967
  }
4984
- /** Prepares the direction's declared dependencies before each server start. */
4985
3968
  async ensureProjectDependencies(args) {
4986
3969
  if (!fs_1.default.existsSync(path_1.default.join(args.cwd, 'package.json')))
4987
3970
  return;
@@ -4990,13 +3973,6 @@ class AgentVariantsOrchestrator {
4990
3973
  signal: args.signal,
4991
3974
  });
4992
3975
  }
4993
- /**
4994
- * Resolve the dev-server working directory for an existing-project variant.
4995
- * WorktreeManager is constructed around the editor/root project, but
4996
- * `start_variants` can target a nested app (for example `examples/blog`).
4997
- * In that case the worktree root is still the git root clone, while the dev
4998
- * server must run from the nested project path.
4999
- */
5000
3976
  async resolveExistingProjectCwd(sessionId, worktreePath, env) {
5001
3977
  const fallback = await this.worktrees.getProjectCwdInWorktree(worktreePath);
5002
3978
  try {
@@ -5014,16 +3990,6 @@ class AgentVariantsOrchestrator {
5014
3990
  return fallback;
5015
3991
  }
5016
3992
  }
5017
- /**
5018
- * After the chosen variant has been renamed into `destinationPath`, move
5019
- * each unchosen sibling worktree into a `<destinationParent>/<slug>-variants/NN-<label>/`
5020
- * folder with its own prepared dependency installation. Writes a manifest documenting all 5 variants (the chosen
5021
- * one with `folder: null` and `chosenPath: '../<slug>'`).
5022
- *
5023
- * Sets `vitePreservedSiblings = true` on session resources so the
5024
- * subsequent teardown skips `cleanupFreshWorktrees` (which would otherwise
5025
- * delete the just-preserved history). Dev servers still get stopped.
5026
- */
5027
3993
  preserveUnchosenVariants(args) {
5028
3994
  const resources = this.resources.get(args.sessionId);
5029
3995
  const runnablePaths = new Map();
@@ -5059,8 +4025,6 @@ class AgentVariantsOrchestrator {
5059
4025
  }
5060
4026
  const record = resources.worktrees.get(variant.workItemId);
5061
4027
  if (!record) {
5062
- // No worktree (e.g. failed variant) — still list it in manifest with
5063
- // null folder so the user can see why it's absent.
5064
4028
  manifestEntries.push({
5065
4029
  variantId: variant.workItemId,
5066
4030
  label,
@@ -5089,8 +4053,6 @@ class AgentVariantsOrchestrator {
5089
4053
  fs_1.default.renameSync(record.worktreePath, dest);
5090
4054
  return dest;
5091
4055
  })();
5092
- // Update the in-memory record so teardown doesn't try to operate on
5093
- // the stale path.
5094
4056
  record.worktreePath = newPath;
5095
4057
  runnablePaths.set(variant.workItemId, `${path_1.default.basename(historyDir)}/${folderName}`);
5096
4058
  manifestEntries.push({
@@ -5129,22 +4091,7 @@ class AgentVariantsOrchestrator {
5129
4091
  resources.vitePreservedSiblings = true;
5130
4092
  return runnablePaths;
5131
4093
  }
5132
- /**
5133
- * Rename `sourceWorktreePath` into `destinationPath`, then replace the
5134
- * worktree's `.git` with a fresh-history init + initial commit. Matches
5135
- * the historical materializeProject behavior of "user sees a fresh repo
5136
- * at destinationPath" so we don't surprise them with a `rivet: variant
5137
- * baseline` commit they didn't intend.
5138
- *
5139
- * The rename is the load-bearing operation: it moves the entire variant
5140
- * tree (template files + materialized node_modules) in O(1) when the
5141
- * source and destination share a volume. The git reset that follows is
5142
- * best-effort housekeeping; a failure there leaves files in place.
5143
- */
5144
4094
  async renameWorktreeIntoDestination(sourceWorktreePath, destinationPath) {
5145
- // destinationPath must not exist for fs.rename to behave as a move.
5146
- // assertDestinationAvailable already enforced that any existing directory
5147
- // contains only `.rivet`, which we preserve across the move.
5148
4095
  const destinationParent = path_1.default.dirname(destinationPath);
5149
4096
  await fs_1.default.promises.mkdir(destinationParent, { recursive: true });
5150
4097
  let preservedRivetParent;
@@ -5191,15 +4138,11 @@ class AgentVariantsOrchestrator {
5191
4138
  force: true,
5192
4139
  });
5193
4140
  }
5194
- // Replace the variant-baseline git history with a fresh init so the
5195
- // user doesn't inherit a `rivet: variant baseline` commit.
5196
4141
  const dotGit = path_1.default.join(destinationPath, '.git');
5197
4142
  try {
5198
4143
  fs_1.default.rmSync(dotGit, { recursive: true, force: true });
5199
4144
  }
5200
4145
  catch {
5201
- // Best-effort — leaving the baseline .git is preferable to failing
5202
- // the commit after we've moved the tree.
5203
4146
  }
5204
4147
  try {
5205
4148
  const git = (0, simple_git_1.simpleGit)(destinationPath);
@@ -5217,22 +4160,12 @@ class AgentVariantsOrchestrator {
5217
4160
  'Initial commit (created with Rivet)',
5218
4161
  ])
5219
4162
  .catch(() => {
5220
- // Best-effort: missing user identity or empty tree leaves the
5221
- // commit step un-applied. Files are still in place.
5222
4163
  });
5223
4164
  }
5224
4165
  catch (err) {
5225
4166
  log.warn(`Initial git history setup at ${destinationPath} failed`, err);
5226
4167
  }
5227
4168
  }
5228
- /**
5229
- * Stop every variant dev server currently running for `resources`. Clears
5230
- * the `devServerProcess` / `port` fields on each record so subsequent
5231
- * teardown logic doesn't try to stop them a second time. Called from
5232
- * `commitVariant` (vite_app rename path) BEFORE the worktree directory is
5233
- * renamed — leaving Vite alive across the rename leaks empty `.vite/`
5234
- * stub dirs at the old paths.
5235
- */
5236
4169
  async stopAllDevServersForSession(resources) {
5237
4170
  this.clearActivePreviewIdleTimer(resources);
5238
4171
  const stops = [];
@@ -5271,7 +4204,6 @@ class AgentVariantsOrchestrator {
5271
4204
  clearTimeout(resources.activePreviewIdleTimer);
5272
4205
  resources.activePreviewIdleTimer = undefined;
5273
4206
  }
5274
- /** @effect Stops idle variant child processes and clears dead preview ports. */
5275
4207
  async stopIdleVariantDevServers(sessionId) {
5276
4208
  const resources = this.resources.get(sessionId);
5277
4209
  if (!resources || resources.cleanupStarted)
@@ -5300,8 +4232,6 @@ class AgentVariantsOrchestrator {
5300
4232
  }
5301
4233
  log.info(`Reclaimed ${expiringWorkItemIds.length} idle variant preview(s) for session ${sessionId} ` +
5302
4234
  `(${stoppedCount} running, ${pendingRestartCount} restarting)`);
5303
- // The next selection restores only the requested Rivet-owned preview;
5304
- // siblings remain stopped until the user asks to view them.
5305
4235
  try {
5306
4236
  this.switchPreviewPort?.(null);
5307
4237
  }
@@ -5317,18 +4247,6 @@ class AgentVariantsOrchestrator {
5317
4247
  resources.activePreviewIdleStop = stop;
5318
4248
  await stop;
5319
4249
  }
5320
- /**
5321
- * Spawn a fresh dev server at the user-facing destinationPath and retarget
5322
- * the proxy so the iframe stays live across commit. Stores the process on
5323
- * `resources.committedDevServer` so teardown can hand it off to the
5324
- * lingering registry instead of killing it. Best-effort: a failure here is
5325
- * non-fatal — the commit still succeeds; the user just has to run
5326
- * `npm run dev` themselves to bring the preview back.
5327
- *
5328
- * `mode` selects the server flavor: `vite_app` spawns Vite via `npm run
5329
- * dev`; `static_preview` spawns the in-tree static file server bound to
5330
- * the destination directory (no install, no build, ~ms startup).
5331
- */
5332
4250
  async startCommittedDevServer(args) {
5333
4251
  const mode = args.mode ?? 'vite_app';
5334
4252
  try {
@@ -5353,14 +4271,6 @@ class AgentVariantsOrchestrator {
5353
4271
  port,
5354
4272
  path: args.destinationPath,
5355
4273
  };
5356
- // Advertise the Rivet-owned server on devServerHealth so the iframe's
5357
- // upstream probe stops reporting `ownership: 'none'`. Distinct from
5358
- // switchPreviewPort: this updates health metadata, switchPreviewPort
5359
- // retargets the proxy. Both fire here because the commit-handoff is
5360
- // the only place Rivet legitimately takes ownership of the dev
5361
- // server — variant cycling and cancel only retarget, they don't
5362
- // touch health (which the user's external dev server owns during a
5363
- // regular session).
5364
4274
  try {
5365
4275
  this.setCommittedDevServerHealth?.(port);
5366
4276
  }
@@ -5381,19 +4291,9 @@ class AgentVariantsOrchestrator {
5381
4291
  return undefined;
5382
4292
  }
5383
4293
  }
5384
- /**
5385
- * Stop any committed dev servers that were left alive past their session's
5386
- * teardown. Called at the start of a new `propose` (so the next session's
5387
- * preview doesn't compete with stale processes) and exposed for explicit
5388
- * shutdown hooks. Best-effort: per-server failures are logged but don't
5389
- * propagate.
5390
- */
5391
4294
  async stopLingeringCommittedDevServers() {
5392
4295
  const entries = [...this.lingeringCommittedDevServers.entries()];
5393
4296
  this.lingeringCommittedDevServers.clear();
5394
- // Clear the Rivet-owned-server advertisement on `devServerHealth` so the
5395
- // probe doesn't keep reporting a port that's about to stop listening.
5396
- // Safe to call even when no committed server existed for this process.
5397
4297
  if (entries.length > 0) {
5398
4298
  try {
5399
4299
  this.setCommittedDevServerHealth?.(null);
@@ -5422,40 +4322,20 @@ class AgentVariantsOrchestrator {
5422
4322
  log.info(`Tearing down session ${sessionId} (reason: ${reason})`);
5423
4323
  resources.dependencyAbortController.abort();
5424
4324
  await Promise.all([...resources.worktrees.values()].map((record) => DependencyPreparationService_1.previewDependencies.settle(record.worktreePath)));
5425
- // Drain in-flight history persists BEFORE deleting worktrees: a tree
5426
- // snapshot's `git add -A --work-tree <worktree>` racing the deletion
5427
- // below doesn't fail — it stages whatever files remain, publishing a
5428
- // silently truncated snapshot. The design doc's ordering constraint
5429
- // ("tree committed before worktree teardown") is enforced here, not
5430
- // just in tests. Best-effort with a bound: never let a wedged git call
5431
- // stall teardown forever.
5432
4325
  await Promise.race([
5433
4326
  this.settleHistoryPersists(),
5434
4327
  new Promise((resolve) => setTimeout(resolve, SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS)),
5435
4328
  ]);
5436
- // Stop dev servers in parallel; ignore individual failures.
5437
- // NOTE: For the fresh vite_app rename path, commitVariant already stopped
5438
- // these dev servers BEFORE the rename (so Vite couldn't recreate `.vite/`
5439
- // stub dirs at the old worktree paths). In that case devServerProcess is
5440
- // already cleared and this loop is a no-op — exactly the desired behavior.
5441
4329
  const stops = [...resources.worktrees.values()]
5442
4330
  .filter((r) => r.devServerProcess)
5443
4331
  .map((r) => this.worktrees
5444
4332
  .stopDevServer(r.devServerProcess)
5445
4333
  .catch((err) => log.warn(`stopDevServer failed for ${sessionId}/${r.workItemId}`, err)));
5446
4334
  await Promise.all(stops);
5447
- // The committed dev server (spawned at destinationPath after a fresh
5448
- // vite_app commit) intentionally outlives this teardown — the iframe is
5449
- // pointed at it via the proxy and the user just chose this project. Hand
5450
- // it off to the lingering registry; it'll be stopped on the next
5451
- // `propose` or explicit shutdown.
5452
4335
  if (resources.committedDevServer && reason === 'committed') {
5453
4336
  this.lingeringCommittedDevServers.set(sessionId, resources.committedDevServer);
5454
4337
  }
5455
4338
  else if (resources.committedDevServer) {
5456
- // Non-committed teardown (cancel/shutdown) with a committed dev server
5457
- // shouldn't happen in current code paths, but stop it defensively so we
5458
- // don't leak procs.
5459
4339
  try {
5460
4340
  await this.worktrees.stopDevServer(resources.committedDevServer.proc);
5461
4341
  }
@@ -5463,10 +4343,6 @@ class AgentVariantsOrchestrator {
5463
4343
  log.warn(`stopDevServer for committed dev server (session ${sessionId}) failed`, err);
5464
4344
  }
5465
4345
  }
5466
- // When a vite_app commit already moved the unchosen worktrees into a
5467
- // sibling history dir, calling cleanupSession would re-delete them. Skip
5468
- // the worktree removal step in that case — the move already cleared the
5469
- // .rivet-variants/ entries for the chosen + preserved variants.
5470
4346
  if (!resources.vitePreservedSiblings) {
5471
4347
  try {
5472
4348
  await this.worktrees.cleanupSession(sessionId, resources.freshDestinationParent);
@@ -5475,10 +4351,6 @@ class AgentVariantsOrchestrator {
5475
4351
  log.warn(`cleanupSession (worktree removal) failed for ${sessionId}`, err);
5476
4352
  }
5477
4353
  }
5478
- // Assigned static workspaces are always Rivet-owned, including existing-
5479
- // project refinement work staged under `.rivet/variant-work` or /tmp.
5480
- // Fresh staticPreviews are also Rivet staging unless commit already moved
5481
- // the selected directory into the destination.
5482
4354
  const ownedArtifactRoots = new Set(resources.workspaceManager.getOwnedArtifactRoots());
5483
4355
  resources.workspaceManager.removeOwnedArtifactWorkspaces();
5484
4356
  const staticDirectories = new Set();
@@ -5536,10 +4408,6 @@ class AgentVariantsOrchestrator {
5536
4408
  }
5537
4409
  }
5538
4410
  exports.AgentVariantsOrchestrator = AgentVariantsOrchestrator;
5539
- /** MCP bridges sometimes serialize the output field as a JSON string instead
5540
- * of a parsed object. Normalize it before field-level inspection. */
5541
- /** Rough byte-size of the agent's output. Used as a proxy for "how much
5542
- * code did the agent write" when comparing HTML vs full-stack flows. */
5543
4411
  function estimateOutputBytes(output) {
5544
4412
  if (output === undefined || output === null)
5545
4413
  return 0;
@@ -5563,28 +4431,11 @@ function normalizeOutput(output) {
5563
4431
  }
5564
4432
  return output;
5565
4433
  }
5566
- /**
5567
- * `true` when `child` is a strict descendant of `parent` (resolved). Used by
5568
- * the static_preview commit branch before rm/rename to make sure we never
5569
- * touch anything outside the variant's workspace.
5570
- */
5571
4434
  function isStrictlyInside(child, parent) {
5572
4435
  const c = path_1.default.resolve(child);
5573
4436
  const p = path_1.default.resolve(parent);
5574
4437
  return c !== p && c.startsWith(p + path_1.default.sep);
5575
4438
  }
5576
- /**
5577
- * Resolve `requestedPath` to an absolute, sandboxed file under `base`, or
5578
- * `undefined` if it escapes the base, doesn't exist, isn't a regular file, or
5579
- * is a hardlink. Shared by `resolveStaticPreviewAssetPath` across the variant's
5580
- * own directory and the host-root fallback so both get identical containment.
5581
- *
5582
- * `base` is expected to be realpath'd by the caller. The requested target is
5583
- * realpath'd here too — without it, a symlink planted under the base (e.g. via
5584
- * a follow-up Write tool call) could pivot outside the sandbox. `requestedPath`
5585
- * is used as Express delivered it (already URL-decoded); decoding again would
5586
- * mangle filenames that legitimately contain `%` (e.g. `100%25.png` on disk).
5587
- */
5588
4439
  function resolveAssetWithinBase(base, requestedPath) {
5589
4440
  const target = path_1.default.resolve(base, '.' + path_1.default.sep + requestedPath);
5590
4441
  if (target !== base && !target.startsWith(base + path_1.default.sep)) {
@@ -5604,11 +4455,6 @@ function resolveAssetWithinBase(base, requestedPath) {
5604
4455
  const stat = fs_1.default.statSync(realTarget);
5605
4456
  if (!stat.isFile())
5606
4457
  return undefined;
5607
- // Hardlinks aren't dereferenced by `realpath` — they ARE the file from a
5608
- // path-resolution perspective, so the realpath check above can't detect
5609
- // them. An agent could `ln /path/to/.env base/x.glb` (hardlink, not
5610
- // symlink) and the resolver would happily serve the secret. Reject
5611
- // anything with multiple links — legitimate assets always have nlink === 1.
5612
4458
  if (stat.nlink !== 1)
5613
4459
  return undefined;
5614
4460
  return realTarget;
@@ -5617,19 +4463,6 @@ function resolveAssetWithinBase(base, requestedPath) {
5617
4463
  return undefined;
5618
4464
  }
5619
4465
  }
5620
- /**
5621
- * Sandbox the agent's `output.assetBase` to a path inside the session
5622
- * workspace. Accepts either an absolute path (used as-is after the
5623
- * within-workspace check) or a path relative to the fresh-session
5624
- * `workspacePath`. Returns `undefined` for non-fresh sessions, missing
5625
- * directories, or paths that escape the workspace via `..` or symlinks.
5626
- *
5627
- * `assetBase` is agent-controlled, so a prompt-injected variant could point
5628
- * it at a symlink whose real target is outside `workspacePath` — and the
5629
- * asset endpoint would then happily serve files like `~/.ssh/id_rsa` or
5630
- * `.env`. Resolving with `fs.realpathSync` collapses symlinks before the
5631
- * containment check, so the check applies to the real target, not the link.
5632
- */
5633
4466
  function resolveStaticPreviewAssetBase(args) {
5634
4467
  if (!args.assetBase)
5635
4468
  return undefined;
@@ -5638,23 +4471,6 @@ function resolveStaticPreviewAssetBase(args) {
5638
4471
  let workspace;
5639
4472
  let resolved;
5640
4473
  try {
5641
- // Defense against an agent that subverts the sandbox by replacing the
5642
- // Rivet-created `workspacePath` directory with a symlink. Plain
5643
- // `realpath` would silently follow that symlink and the containment
5644
- // check below would then trust the wrong root.
5645
- //
5646
- // Two layers:
5647
- // 1. `lstat` the workspacePath itself — if it's a symlink (rather
5648
- // than a real directory Rivet created), reject outright. This
5649
- // catches the obvious swap `ln -sf $HOME <workspacePath>` and the
5650
- // subtler swap to a sibling like `<workspaceRoot>` itself
5651
- // (which would pass any subsequent containment check based on
5652
- // ancestor matching).
5653
- // 2. realpath both and require the resolved workspacePath to be a
5654
- // STRICT descendant of the resolved workspaceRoot — equal is not
5655
- // enough (a symlink to workspaceRoot would otherwise be accepted
5656
- // and the asset route would then serve files at the project
5657
- // root, e.g. `.env`).
5658
4474
  const wsStat = fs_1.default.lstatSync(args.projectContext.workspacePath);
5659
4475
  if (wsStat.isSymbolicLink()) {
5660
4476
  log.warn(`Static preview workspacePath ${args.projectContext.workspacePath} is a symlink — refusing assetBase`);
@@ -5716,11 +4532,6 @@ function buildStaticPreviewDocument(input) {
5716
4532
  const style = input.css ? `<style>\n${input.css}\n</style>` : '';
5717
4533
  const script = input.js ? `<script>\n${input.js}\n</script>` : '';
5718
4534
  if (/<!doctype html>|<html[\s>]/i.test(input.html)) {
5719
- // Full document: inject css before </head> and js before </body>. The
5720
- // agent often passes a complete `<!doctype html>...` blob with css/js
5721
- // alongside; without this they're silently dropped and the variant ships
5722
- // unstyled and non-interactive. Falls back to appending to the end if
5723
- // the closing tag isn't found.
5724
4535
  let doc = input.html;
5725
4536
  if (style) {
5726
4537
  if (/<\/head>/i.test(doc)) {
@@ -5754,15 +4565,8 @@ ${input.html}
5754
4565
  </html>`;
5755
4566
  }
5756
4567
  function countDiffFiles(diff) {
5757
- // Each file in a unified diff starts with "diff --git ".
5758
4568
  return (diff.match(/^diff --git /gm) ?? []).length;
5759
4569
  }
5760
- /**
5761
- * Count source files under a materialized fresh-project destination,
5762
- * skipping install artifacts (`node_modules`, `.git`, build outputs) so the
5763
- * commit telemetry / chip count reflects the agent-visible surface area
5764
- * rather than the install footprint.
5765
- */
5766
4570
  function countWorktreeFiles(destinationPath) {
5767
4571
  let count = 0;
5768
4572
  const walk = (dir) => {
@@ -5795,8 +4599,6 @@ const enrichDesignSource = (design) => {
5795
4599
  };
5796
4600
  };
5797
4601
  const toActiveProjectContext = (projectContext) => {
5798
- // Source count + grounding are derived purely from the read-only context
5799
- // bundle now that `sourceContext` intake is gone.
5800
4602
  const sourceCount = projectContext.variantContext?.userContext.filter((source) => source.transport !== 'prompt').length ?? 0;
5801
4603
  const hasSourceContextSummary = Boolean(sourceCount > 0 ||
5802
4604
  (projectContext.variantContext?.rivetMetadata.length ?? 0) > 0);
@@ -5839,18 +4641,6 @@ const toActiveProjectContext = (projectContext) => {
5839
4641
  : {}),
5840
4642
  };
5841
4643
  };
5842
- /**
5843
- * Resolve the user-facing supporting artifacts for a session.
5844
- *
5845
- * For 0→1 (`fresh`) sessions with a populated `designContext`, each slot is
5846
- * turned into a `design_context` artifact that links to Rivet-hosted
5847
- * DESIGN.md views:
5848
- * - `slug` entries resolve bundled catalog markdown via the design catalog.
5849
- * - `markdown` entries (Agent Browser / inspiration extractor output) carry
5850
- * their stored markdown when the linked route is requested.
5851
- * Slots whose markdown can't be resolved are skipped so the UI never renders
5852
- * a metadata-only DESIGN.md row.
5853
- */
5854
4644
  const buildSessionArtifacts = (sessionId, projectContext) => {
5855
4645
  const artifacts = buildResolvedDesignContextArtifacts(projectContext);
5856
4646
  return artifacts.map(({ content: _content, ...artifact }) => ({
@@ -6188,7 +4978,6 @@ const renderDesignMarkdown = (markdown, artifactLabel) => {
6188
4978
  const headingText = headingMatch[2].trim();
6189
4979
  const isDuplicateTitle = headingText === artifactLabel ||
6190
4980
  headingText === `${artifactLabel} DESIGN.md`;
6191
- // The viewer header already renders the artifact title.
6192
4981
  if (level === 1 && !skippedFirstH1 && isDuplicateTitle) {
6193
4982
  skippedFirstH1 = true;
6194
4983
  return;
@@ -6230,14 +5019,6 @@ const escapeHtml = (value) => {
6230
5019
  .replace(/"/g, '&quot;')
6231
5020
  .replace(/'/g, '&#39;');
6232
5021
  };
6233
- /**
6234
- * Resolve a per-variant design context entry into the raw DESIGN.md markdown
6235
- * the worktree scaffolder writes, plus a small `designSource` descriptor for
6236
- * the variant manifest. Slug entries resolve through the bundled catalog;
6237
- * markdown entries (Agent Browser / inspiration extractor output) carry their
6238
- * stored markdown verbatim. Returns null when the entry is missing or the
6239
- * slug doesn't resolve to bundled markdown.
6240
- */
6241
5022
  const resolveDesignArtifact = (entry) => {
6242
5023
  if (!entry)
6243
5024
  return null;
@@ -6462,7 +5243,6 @@ function copyStaticPreviewDirectory(src, dest) {
6462
5243
  }
6463
5244
  }
6464
5245
  }
6465
- /** Prepares an isolated project through its selected package manager. */
6466
5246
  const defaultInstallDependencies = async (worktreePath, options) => {
6467
5247
  await DependencyPreparationService_1.previewDependencies.prepare({
6468
5248
  cwd: worktreePath,
@@ -6471,14 +5251,6 @@ const defaultInstallDependencies = async (worktreePath, options) => {
6471
5251
  signal: options?.signal,
6472
5252
  });
6473
5253
  };
6474
- /**
6475
- * Turn the invocation a live dev server actually booted with into a
6476
- * port-parameterized replay recipe. The resolution bakes the allocated port
6477
- * into args/env (`--port <n>`, `PORT=<n>`) — storing that verbatim would
6478
- * bake in a dead port, so occurrences of the port (digit-boundary-guarded so
6479
- * incidental digit runs survive) become `${PORT}` for replay to substitute.
6480
- * `cwd` is stored relative to the snapshot root per the tree-root contract.
6481
- */
6482
5254
  const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
6483
5255
  const portPattern = new RegExp(`(?<![0-9])${port}(?![0-9])`, 'g');
6484
5256
  const sub = (value) => value.replace(portPattern, '${PORT}');
@@ -6490,19 +5262,6 @@ const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
6490
5262
  envTemplate: Object.fromEntries(Object.entries(dev.env).map(([key, value]) => [key, sub(value)])),
6491
5263
  };
6492
5264
  };
6493
- /**
6494
- * Whether an install at `cwd` stays inside the Rivet-owned worktree.
6495
- * A linked `node_modules` can point at another project's install; running a
6496
- * package manager through it would mutate dependencies outside this worktree.
6497
- * Install is safe only
6498
- * when `node_modules` is absent (a nested standalone package — the install
6499
- * creates a worktree-local dir) or a real directory owned by the worktree.
6500
- *
6501
- * Complements DependencyPreparationService.assertOwnedInstall rather than
6502
- * duplicating it: this stricter check (any symlink, even one resolving
6503
- * inside the worktree) decides whether an install RETRY is worth attempting,
6504
- * while the service enforces containment on every install it runs.
6505
- */
6506
5265
  const canInstallWithoutTouchingHost = (cwd) => {
6507
5266
  try {
6508
5267
  return !fs_1.default.lstatSync(path_1.default.join(cwd, 'node_modules')).isSymbolicLink();
@@ -6511,15 +5270,6 @@ const canInstallWithoutTouchingHost = (cwd) => {
6511
5270
  return true;
6512
5271
  }
6513
5272
  };
6514
- /**
6515
- * Fail fast — before spawning anything — when the package.json at `cwd`
6516
- * positively lacks the dev script we're about to invoke. Without this the
6517
- * spawn exits with the package manager's "missing script" error after a full
6518
- * boot round-trip and surfaces as an opaque `exited` failure; with it the
6519
- * user gets an actionable message naming the scripts that DO exist. Missing
6520
- * or unparseable package.json is NOT treated as a failure here — other paths
6521
- * own those cases, and the spawn's own error is more specific.
6522
- */
6523
5273
  const assertDevScriptExists = (cwd, scriptName) => {
6524
5274
  let scripts;
6525
5275
  try {
@@ -6548,16 +5298,6 @@ const assertDevScriptExists = (cwd, scriptName) => {
6548
5298
  : '',
6549
5299
  });
6550
5300
  };
6551
- /**
6552
- * True when `a` and `b` (or the closest existing ancestor of each) live on
6553
- * the same filesystem volume. Used by commitVariant to decide between an
6554
- * O(1) rename and a recursive copy-with-reinstall fallback.
6555
- *
6556
- * `destinationPath` for fresh sessions does not exist yet (we'd fail the
6557
- * "destination must be empty" guard otherwise), so we compare against its
6558
- * parent directory which is guaranteed to exist (createZeroToOneTool either
6559
- * created it or validated it).
6560
- */
6561
5301
  function areSameVolume(a, b) {
6562
5302
  try {
6563
5303
  const statA = fs_1.default.statSync(a);
@@ -6569,7 +5309,6 @@ function areSameVolume(a, b) {
6569
5309
  return false;
6570
5310
  }
6571
5311
  }
6572
- /** Clears a borrowed install so a moved generated project prepares its own dependencies. */
6573
5312
  async function resolveNodeModulesSymlink(worktreePath) {
6574
5313
  const nodeModulesPath = path_1.default.join(worktreePath, 'node_modules');
6575
5314
  try {
@@ -6611,16 +5350,8 @@ const defaultMaterializeProject = async (sourceWorktreePath, destinationPath) =>
6611
5350
  'Initial commit (created with Rivet)',
6612
5351
  ])
6613
5352
  .catch(() => {
6614
- // Best-effort: a missing user identity or empty tree leaves the
6615
- // commit step un-applied. The destination still has the files.
6616
5353
  });
6617
5354
  };
6618
- /**
6619
- * Synthesize a fallback brief body for a human-direct unified start slot.
6620
- * Agent callers provide structured briefs before starting. Human-direct
6621
- * batches get stable, slot-specific focus statements without another model
6622
- * call so workers do not independently invent overlapping directions.
6623
- */
6624
5355
  function synthesizeUnifiedBriefBody(prompt, index, total) {
6625
5356
  const trimmed = prompt.trim().replace(/\s+/g, ' ').slice(0, 200);
6626
5357
  const intent = trimmed.length > 0 ? trimmed : 'Create this variant';