rivet-design 0.17.4 → 0.18.0

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 (938) hide show
  1. package/bin/rivet.js +0 -16
  2. package/dist/agent-variants/SessionStore.d.ts +5 -240
  3. package/dist/agent-variants/SessionStore.d.ts.map +1 -1
  4. package/dist/agent-variants/SessionStore.js +42 -371
  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 +6 -598
  15. package/dist/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
  16. package/dist/agent-variants/WorktreeOrchestrator.js +55 -1288
  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 +2016 -600
  31. package/dist/agent-variants/contracts.d.ts.map +1 -1
  32. package/dist/agent-variants/contracts.js +10 -174
  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 +6 -7
  71. package/dist/agent-variants/variantContext.d.ts.map +1 -1
  72. package/dist/agent-variants/variantContext.js +69 -10
  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 +1 -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 +126 -106
  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/profile.d.ts +3 -0
  127. package/dist/cli/commands/profile.d.ts.map +1 -0
  128. package/dist/cli/commands/profile.js +192 -0
  129. package/dist/cli/commands/profile.js.map +1 -0
  130. package/dist/cli/commands/reference.d.ts +0 -5
  131. package/dist/cli/commands/reference.d.ts.map +1 -1
  132. package/dist/cli/commands/reference.js +4 -27
  133. package/dist/cli/commands/reference.js.map +1 -1
  134. package/dist/cli/commands/serve.d.ts +0 -5
  135. package/dist/cli/commands/serve.d.ts.map +1 -1
  136. package/dist/cli/commands/serve.js +0 -34
  137. package/dist/cli/commands/serve.js.map +1 -1
  138. package/dist/cli/commands/shared.d.ts +0 -16
  139. package/dist/cli/commands/shared.d.ts.map +1 -1
  140. package/dist/cli/commands/shared.js +0 -19
  141. package/dist/cli/commands/shared.js.map +1 -1
  142. package/dist/cli/commands/status.d.ts +0 -6
  143. package/dist/cli/commands/status.d.ts.map +1 -1
  144. package/dist/cli/commands/status.js +0 -11
  145. package/dist/cli/commands/status.js.map +1 -1
  146. package/dist/cli/commands/stop.d.ts +0 -5
  147. package/dist/cli/commands/stop.d.ts.map +1 -1
  148. package/dist/cli/commands/stop.js +0 -6
  149. package/dist/cli/commands/stop.js.map +1 -1
  150. package/dist/cli/commands/update.d.ts +0 -1
  151. package/dist/cli/commands/update.d.ts.map +1 -1
  152. package/dist/cli/commands/update.js +0 -1
  153. package/dist/cli/commands/update.js.map +1 -1
  154. package/dist/cli/commands/variants.d.ts +0 -1
  155. package/dist/cli/commands/variants.d.ts.map +1 -1
  156. package/dist/cli/commands/variants.js +13 -32
  157. package/dist/cli/commands/variants.js.map +1 -1
  158. package/dist/cli/commands/wait.d.ts +0 -21
  159. package/dist/cli/commands/wait.d.ts.map +1 -1
  160. package/dist/cli/commands/wait.js +0 -23
  161. package/dist/cli/commands/wait.js.map +1 -1
  162. package/dist/cli/entry.d.ts +0 -10
  163. package/dist/cli/entry.d.ts.map +1 -1
  164. package/dist/cli/entry.js +0 -13
  165. package/dist/cli/entry.js.map +1 -1
  166. package/dist/cli/envelope.d.ts +1 -25
  167. package/dist/cli/envelope.d.ts.map +1 -1
  168. package/dist/cli/envelope.js +0 -19
  169. package/dist/cli/envelope.js.map +1 -1
  170. package/dist/cli/flags.d.ts +0 -7
  171. package/dist/cli/flags.d.ts.map +1 -1
  172. package/dist/cli/flags.js +0 -7
  173. package/dist/cli/flags.js.map +1 -1
  174. package/dist/cli/handoff.d.ts +0 -33
  175. package/dist/cli/handoff.d.ts.map +1 -1
  176. package/dist/cli/handoff.js +0 -42
  177. package/dist/cli/handoff.js.map +1 -1
  178. package/dist/cli/handoffStore.d.ts +0 -11
  179. package/dist/cli/handoffStore.d.ts.map +1 -1
  180. package/dist/cli/handoffStore.js +0 -10
  181. package/dist/cli/handoffStore.js.map +1 -1
  182. package/dist/cli/hostWorkNextAction.d.ts +0 -11
  183. package/dist/cli/hostWorkNextAction.d.ts.map +1 -1
  184. package/dist/cli/hostWorkNextAction.js +0 -4
  185. package/dist/cli/hostWorkNextAction.js.map +1 -1
  186. package/dist/cli/io.d.ts +0 -9
  187. package/dist/cli/io.d.ts.map +1 -1
  188. package/dist/cli/io.js +0 -1
  189. package/dist/cli/io.js.map +1 -1
  190. package/dist/cli/resolveDefaultNodeEnv.d.ts +0 -5
  191. package/dist/cli/resolveDefaultNodeEnv.d.ts.map +1 -1
  192. package/dist/cli/resolveDefaultNodeEnv.js +0 -5
  193. package/dist/cli/resolveDefaultNodeEnv.js.map +1 -1
  194. package/dist/cli/router.d.ts +0 -21
  195. package/dist/cli/router.d.ts.map +1 -1
  196. package/dist/cli/router.js +8 -46
  197. package/dist/cli/router.js.map +1 -1
  198. package/dist/cli/runnerSelection.d.ts +0 -58
  199. package/dist/cli/runnerSelection.d.ts.map +1 -1
  200. package/dist/cli/runnerSelection.js +0 -16
  201. package/dist/cli/runnerSelection.js.map +1 -1
  202. package/dist/cli/serverHandshake.d.ts +0 -36
  203. package/dist/cli/serverHandshake.d.ts.map +1 -1
  204. package/dist/cli/serverHandshake.js +0 -29
  205. package/dist/cli/serverHandshake.js.map +1 -1
  206. package/dist/cli/serverUnavailable.d.ts +0 -1
  207. package/dist/cli/serverUnavailable.d.ts.map +1 -1
  208. package/dist/cli/serverUnavailable.js +0 -1
  209. package/dist/cli/serverUnavailable.js.map +1 -1
  210. package/dist/cli/serverVersion.d.ts +0 -22
  211. package/dist/cli/serverVersion.d.ts.map +1 -1
  212. package/dist/cli/serverVersion.js +0 -12
  213. package/dist/cli/serverVersion.js.map +1 -1
  214. package/dist/cli/telemetry.d.ts +0 -4
  215. package/dist/cli/telemetry.d.ts.map +1 -1
  216. package/dist/cli/telemetry.js +0 -4
  217. package/dist/cli/telemetry.js.map +1 -1
  218. package/dist/config/evaluateFlags.d.ts +0 -4
  219. package/dist/config/evaluateFlags.d.ts.map +1 -1
  220. package/dist/config/evaluateFlags.js +0 -11
  221. package/dist/config/evaluateFlags.js.map +1 -1
  222. package/dist/config/featureFlagUserKey.d.ts +0 -3
  223. package/dist/config/featureFlagUserKey.d.ts.map +1 -1
  224. package/dist/config/featureFlagUserKey.js +0 -3
  225. package/dist/config/featureFlagUserKey.js.map +1 -1
  226. package/dist/config/flags.d.ts +0 -14
  227. package/dist/config/flags.d.ts.map +1 -1
  228. package/dist/config/flags.js +0 -27
  229. package/dist/config/flags.js.map +1 -1
  230. package/dist/config/proxy.d.ts +0 -3
  231. package/dist/config/proxy.d.ts.map +1 -1
  232. package/dist/config/proxy.js +0 -11
  233. package/dist/config/proxy.js.map +1 -1
  234. package/dist/config/telemetry.d.ts +0 -13
  235. package/dist/config/telemetry.d.ts.map +1 -1
  236. package/dist/config/telemetry.js +0 -13
  237. package/dist/config/telemetry.js.map +1 -1
  238. package/dist/config/telemetryContract.d.ts +0 -1
  239. package/dist/config/telemetryContract.d.ts.map +1 -1
  240. package/dist/config/telemetryContract.js +0 -1
  241. package/dist/config/telemetryContract.js.map +1 -1
  242. package/dist/hosts/workerDefaults.d.ts +0 -69
  243. package/dist/hosts/workerDefaults.d.ts.map +1 -1
  244. package/dist/hosts/workerDefaults.js +0 -68
  245. package/dist/hosts/workerDefaults.js.map +1 -1
  246. package/dist/index-core.d.ts.map +1 -1
  247. package/dist/index-core.js +0 -2
  248. package/dist/index-core.js.map +1 -1
  249. package/dist/index.d.ts +0 -20
  250. package/dist/index.d.ts.map +1 -1
  251. package/dist/index.js +2 -105
  252. package/dist/index.js.map +1 -1
  253. package/dist/install/allowlists.d.ts +0 -32
  254. package/dist/install/allowlists.d.ts.map +1 -1
  255. package/dist/install/allowlists.js +0 -44
  256. package/dist/install/allowlists.js.map +1 -1
  257. package/dist/install/automaticCliUpdate.d.ts +0 -6
  258. package/dist/install/automaticCliUpdate.d.ts.map +1 -1
  259. package/dist/install/automaticCliUpdate.js +0 -13
  260. package/dist/install/automaticCliUpdate.js.map +1 -1
  261. package/dist/install/channelCli.d.ts +0 -1
  262. package/dist/install/channelCli.d.ts.map +1 -1
  263. package/dist/install/channelCli.js +0 -3
  264. package/dist/install/channelCli.js.map +1 -1
  265. package/dist/install/channelManager.d.ts +0 -14
  266. package/dist/install/channelManager.d.ts.map +1 -1
  267. package/dist/install/channelManager.js +0 -22
  268. package/dist/install/channelManager.js.map +1 -1
  269. package/dist/install/codexGuidance.d.ts +0 -1
  270. package/dist/install/codexGuidance.d.ts.map +1 -1
  271. package/dist/install/codexGuidance.js +0 -7
  272. package/dist/install/codexGuidance.js.map +1 -1
  273. package/dist/install/globalBootstrap.d.ts +0 -25
  274. package/dist/install/globalBootstrap.d.ts.map +1 -1
  275. package/dist/install/globalBootstrap.js +0 -10
  276. package/dist/install/globalBootstrap.js.map +1 -1
  277. package/dist/install/harnesses.d.ts +0 -66
  278. package/dist/install/harnesses.d.ts.map +1 -1
  279. package/dist/install/harnesses.js +0 -60
  280. package/dist/install/harnesses.js.map +1 -1
  281. package/dist/install/installationChannel.d.ts +0 -1
  282. package/dist/install/installationChannel.d.ts.map +1 -1
  283. package/dist/install/installationChannel.js +0 -1
  284. package/dist/install/installationChannel.js.map +1 -1
  285. package/dist/install/legacyMcp.d.ts +0 -23
  286. package/dist/install/legacyMcp.d.ts.map +1 -1
  287. package/dist/install/legacyMcp.js +3 -46
  288. package/dist/install/legacyMcp.js.map +1 -1
  289. package/dist/install/mcpRegistration.d.ts +0 -41
  290. package/dist/install/mcpRegistration.d.ts.map +1 -1
  291. package/dist/install/mcpRegistration.js +2 -70
  292. package/dist/install/mcpRegistration.js.map +1 -1
  293. package/dist/library/HubClient.d.ts +1 -2
  294. package/dist/library/HubClient.d.ts.map +1 -1
  295. package/dist/library/HubClient.js +11 -5
  296. package/dist/library/HubClient.js.map +1 -1
  297. package/dist/library/HubServer.d.ts +0 -1
  298. package/dist/library/HubServer.d.ts.map +1 -1
  299. package/dist/library/HubServer.js +19 -1
  300. package/dist/library/HubServer.js.map +1 -1
  301. package/dist/library/StaticPreviewServer.d.ts +0 -1
  302. package/dist/library/StaticPreviewServer.d.ts.map +1 -1
  303. package/dist/library/StaticPreviewServer.js +0 -1
  304. package/dist/library/StaticPreviewServer.js.map +1 -1
  305. package/dist/library/http.d.ts +0 -2
  306. package/dist/library/http.d.ts.map +1 -1
  307. package/dist/library/http.js +0 -2
  308. package/dist/library/http.js.map +1 -1
  309. package/dist/library/importFiles.d.ts +0 -6
  310. package/dist/library/importFiles.d.ts.map +1 -1
  311. package/dist/library/importFiles.js +45 -11
  312. package/dist/library/importFiles.js.map +1 -1
  313. package/dist/mcp/changeBatchClassification.d.ts +0 -40
  314. package/dist/mcp/changeBatchClassification.d.ts.map +1 -1
  315. package/dist/mcp/changeBatchClassification.js +0 -34
  316. package/dist/mcp/changeBatchClassification.js.map +1 -1
  317. package/dist/prompts/commentVariationPrompts.d.ts +0 -5
  318. package/dist/prompts/commentVariationPrompts.d.ts.map +1 -1
  319. package/dist/prompts/commentVariationPrompts.js +0 -5
  320. package/dist/prompts/commentVariationPrompts.js.map +1 -1
  321. package/dist/prototype-host.js +0 -15
  322. package/dist/prototype-host.js.map +1 -1
  323. package/dist/proxy-middleware/preview-bridge.d.ts +0 -2
  324. package/dist/proxy-middleware/preview-bridge.d.ts.map +1 -1
  325. package/dist/proxy-middleware/preview-bridge.js +0 -2
  326. package/dist/proxy-middleware/preview-bridge.js.map +1 -1
  327. package/dist/proxy-middleware/preview-connections.d.ts +0 -1
  328. package/dist/proxy-middleware/preview-connections.d.ts.map +1 -1
  329. package/dist/proxy-middleware/preview-connections.js +0 -1
  330. package/dist/proxy-middleware/preview-connections.js.map +1 -1
  331. package/dist/proxy-middleware/proxy-config.d.ts +0 -12
  332. package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
  333. package/dist/proxy-middleware/proxy-config.js +2 -49
  334. package/dist/proxy-middleware/proxy-config.js.map +1 -1
  335. package/dist/routes/account.d.ts +0 -1
  336. package/dist/routes/account.d.ts.map +1 -1
  337. package/dist/routes/account.js +0 -2
  338. package/dist/routes/account.js.map +1 -1
  339. package/dist/routes/agentVariants.d.ts +0 -15
  340. package/dist/routes/agentVariants.d.ts.map +1 -1
  341. package/dist/routes/agentVariants.js +132 -329
  342. package/dist/routes/agentVariants.js.map +1 -1
  343. package/dist/routes/cli.d.ts +0 -17
  344. package/dist/routes/cli.d.ts.map +1 -1
  345. package/dist/routes/cli.js +0 -13
  346. package/dist/routes/cli.js.map +1 -1
  347. package/dist/routes/emptyStatePage.d.ts +0 -12
  348. package/dist/routes/emptyStatePage.d.ts.map +1 -1
  349. package/dist/routes/emptyStatePage.js +0 -12
  350. package/dist/routes/emptyStatePage.js.map +1 -1
  351. package/dist/routes/git.d.ts.map +1 -1
  352. package/dist/routes/git.js +0 -13
  353. package/dist/routes/git.js.map +1 -1
  354. package/dist/routes/inlineStartTracker.d.ts +0 -16
  355. package/dist/routes/inlineStartTracker.d.ts.map +1 -1
  356. package/dist/routes/inlineStartTracker.js.map +1 -1
  357. package/dist/routes/integrations.d.ts +0 -6
  358. package/dist/routes/integrations.d.ts.map +1 -1
  359. package/dist/routes/integrations.js +0 -6
  360. package/dist/routes/integrations.js.map +1 -1
  361. package/dist/routes/library/app.d.ts +0 -1
  362. package/dist/routes/library/app.d.ts.map +1 -1
  363. package/dist/routes/library/app.js +1 -3
  364. package/dist/routes/library/app.js.map +1 -1
  365. package/dist/routes/library/index.d.ts +0 -1
  366. package/dist/routes/library/index.d.ts.map +1 -1
  367. package/dist/routes/library/index.js +3 -1
  368. package/dist/routes/library/index.js.map +1 -1
  369. package/dist/routes/library/middleware.d.ts +0 -3
  370. package/dist/routes/library/middleware.d.ts.map +1 -1
  371. package/dist/routes/library/middleware.js +0 -4
  372. package/dist/routes/library/middleware.js.map +1 -1
  373. package/dist/routes/library/navigation.d.ts +0 -1
  374. package/dist/routes/library/navigation.d.ts.map +1 -1
  375. package/dist/routes/library/navigation.js +0 -1
  376. package/dist/routes/library/navigation.js.map +1 -1
  377. package/dist/routes/library/profiles.d.ts +5 -0
  378. package/dist/routes/library/profiles.d.ts.map +1 -0
  379. package/dist/routes/library/profiles.js +182 -0
  380. package/dist/routes/library/profiles.js.map +1 -0
  381. package/dist/routes/library/projects.d.ts +0 -1
  382. package/dist/routes/library/projects.d.ts.map +1 -1
  383. package/dist/routes/library/projects.js +0 -1
  384. package/dist/routes/library/projects.js.map +1 -1
  385. package/dist/routes/library/schemas.d.ts +2 -2
  386. package/dist/routes/library/staticPreview.d.ts +0 -1
  387. package/dist/routes/library/staticPreview.d.ts.map +1 -1
  388. package/dist/routes/library/staticPreview.js +0 -1
  389. package/dist/routes/library/staticPreview.js.map +1 -1
  390. package/dist/routes/library/types.d.ts +2 -0
  391. package/dist/routes/library/types.d.ts.map +1 -1
  392. package/dist/routes/library/variants.d.ts +0 -1
  393. package/dist/routes/library/variants.d.ts.map +1 -1
  394. package/dist/routes/library/variants.js +0 -1
  395. package/dist/routes/library/variants.js.map +1 -1
  396. package/dist/routes/mcp.d.ts +0 -3
  397. package/dist/routes/mcp.d.ts.map +1 -1
  398. package/dist/routes/mcp.js +0 -5
  399. package/dist/routes/mcp.js.map +1 -1
  400. package/dist/routes/prototypeHost.d.ts +0 -2
  401. package/dist/routes/prototypeHost.d.ts.map +1 -1
  402. package/dist/routes/prototypeHost.js +6 -32
  403. package/dist/routes/prototypeHost.js.map +1 -1
  404. package/dist/routes/static.d.ts +0 -3
  405. package/dist/routes/static.d.ts.map +1 -1
  406. package/dist/routes/static.js +0 -6
  407. package/dist/routes/static.js.map +1 -1
  408. package/dist/routes/support.d.ts +0 -3
  409. package/dist/routes/support.d.ts.map +1 -1
  410. package/dist/routes/support.js +0 -3
  411. package/dist/routes/support.js.map +1 -1
  412. package/dist/server.d.ts +0 -42
  413. package/dist/server.d.ts.map +1 -1
  414. package/dist/server.js +1 -129
  415. package/dist/server.js.map +1 -1
  416. package/dist/services/AuthService.d.ts +0 -76
  417. package/dist/services/AuthService.d.ts.map +1 -1
  418. package/dist/services/AuthService.js +0 -112
  419. package/dist/services/AuthService.js.map +1 -1
  420. package/dist/services/BrowserAgentClient.d.ts +1 -21
  421. package/dist/services/BrowserAgentClient.d.ts.map +1 -1
  422. package/dist/services/BrowserAgentClient.js +0 -10
  423. package/dist/services/BrowserAgentClient.js.map +1 -1
  424. package/dist/services/BundleStore.d.ts +0 -18
  425. package/dist/services/BundleStore.d.ts.map +1 -1
  426. package/dist/services/BundleStore.js +0 -10
  427. package/dist/services/BundleStore.js.map +1 -1
  428. package/dist/services/CliLogForwarder.d.ts +0 -26
  429. package/dist/services/CliLogForwarder.d.ts.map +1 -1
  430. package/dist/services/CliLogForwarder.js +1 -33
  431. package/dist/services/CliLogForwarder.js.map +1 -1
  432. package/dist/services/CommitMessageGenerator.d.ts +0 -6
  433. package/dist/services/CommitMessageGenerator.d.ts.map +1 -1
  434. package/dist/services/CommitMessageGenerator.js +0 -3
  435. package/dist/services/CommitMessageGenerator.js.map +1 -1
  436. package/dist/services/ComponentSearchService.d.ts +2 -16
  437. package/dist/services/ComponentSearchService.d.ts.map +1 -1
  438. package/dist/services/ComponentSearchService.js +2 -56
  439. package/dist/services/ComponentSearchService.js.map +1 -1
  440. package/dist/services/ConfigManager.d.ts +0 -113
  441. package/dist/services/ConfigManager.d.ts.map +1 -1
  442. package/dist/services/ConfigManager.js +0 -101
  443. package/dist/services/ConfigManager.js.map +1 -1
  444. package/dist/services/DependencyPreparationService.d.ts +0 -6
  445. package/dist/services/DependencyPreparationService.d.ts.map +1 -1
  446. package/dist/services/DependencyPreparationService.js +0 -22
  447. package/dist/services/DependencyPreparationService.js.map +1 -1
  448. package/dist/services/DevServerRuntimeService.d.ts +0 -20
  449. package/dist/services/DevServerRuntimeService.d.ts.map +1 -1
  450. package/dist/services/DevServerRuntimeService.js +0 -46
  451. package/dist/services/DevServerRuntimeService.js.map +1 -1
  452. package/dist/services/FeatureFlagService.d.ts +0 -15
  453. package/dist/services/FeatureFlagService.d.ts.map +1 -1
  454. package/dist/services/FeatureFlagService.js +0 -23
  455. package/dist/services/FeatureFlagService.js.map +1 -1
  456. package/dist/services/GatewayClient.d.ts +0 -27
  457. package/dist/services/GatewayClient.d.ts.map +1 -1
  458. package/dist/services/GatewayClient.js +0 -25
  459. package/dist/services/GatewayClient.js.map +1 -1
  460. package/dist/services/HistoryReplayService.d.ts +0 -31
  461. package/dist/services/HistoryReplayService.d.ts.map +1 -1
  462. package/dist/services/HistoryReplayService.js +2 -55
  463. package/dist/services/HistoryReplayService.js.map +1 -1
  464. package/dist/services/HubDiscovery.d.ts +0 -8
  465. package/dist/services/HubDiscovery.d.ts.map +1 -1
  466. package/dist/services/HubDiscovery.js +0 -8
  467. package/dist/services/HubDiscovery.js.map +1 -1
  468. package/dist/services/HubNavigation.d.ts +0 -6
  469. package/dist/services/HubNavigation.d.ts.map +1 -1
  470. package/dist/services/HubNavigation.js +5 -8
  471. package/dist/services/HubNavigation.js.map +1 -1
  472. package/dist/services/IntegrationsClient.d.ts +20 -38
  473. package/dist/services/IntegrationsClient.d.ts.map +1 -1
  474. package/dist/services/IntegrationsClient.js +71 -31
  475. package/dist/services/IntegrationsClient.js.map +1 -1
  476. package/dist/services/LocalGitService.d.ts +0 -57
  477. package/dist/services/LocalGitService.d.ts.map +1 -1
  478. package/dist/services/LocalGitService.js +4 -85
  479. package/dist/services/LocalGitService.js.map +1 -1
  480. package/dist/services/MCPOnboardingTelemetry.d.ts +0 -9
  481. package/dist/services/MCPOnboardingTelemetry.d.ts.map +1 -1
  482. package/dist/services/MCPOnboardingTelemetry.js +0 -9
  483. package/dist/services/MCPOnboardingTelemetry.js.map +1 -1
  484. package/dist/services/MCPVariantsTelemetry.d.ts +0 -2
  485. package/dist/services/MCPVariantsTelemetry.d.ts.map +1 -1
  486. package/dist/services/MCPVariantsTelemetry.js +0 -2
  487. package/dist/services/MCPVariantsTelemetry.js.map +1 -1
  488. package/dist/services/OperatingSystemServices.d.ts +0 -12
  489. package/dist/services/OperatingSystemServices.d.ts.map +1 -1
  490. package/dist/services/OperatingSystemServices.js +0 -7
  491. package/dist/services/OperatingSystemServices.js.map +1 -1
  492. package/dist/services/PRTitleGenerator.d.ts +0 -7
  493. package/dist/services/PRTitleGenerator.d.ts.map +1 -1
  494. package/dist/services/PRTitleGenerator.js +0 -3
  495. package/dist/services/PRTitleGenerator.js.map +1 -1
  496. package/dist/services/ProjectCardPreviews.d.ts +0 -5
  497. package/dist/services/ProjectCardPreviews.d.ts.map +1 -1
  498. package/dist/services/ProjectCardPreviews.js +0 -5
  499. package/dist/services/ProjectCardPreviews.js.map +1 -1
  500. package/dist/services/ProjectDetectionService.d.ts +0 -4
  501. package/dist/services/ProjectDetectionService.d.ts.map +1 -1
  502. package/dist/services/ProjectDetectionService.js +2 -44
  503. package/dist/services/ProjectDetectionService.js.map +1 -1
  504. package/dist/services/ProjectFolderPicker.d.ts +0 -3
  505. package/dist/services/ProjectFolderPicker.d.ts.map +1 -1
  506. package/dist/services/ProjectFolderPicker.js +0 -4
  507. package/dist/services/ProjectFolderPicker.js.map +1 -1
  508. package/dist/services/ProjectImport.d.ts +0 -1
  509. package/dist/services/ProjectImport.d.ts.map +1 -1
  510. package/dist/services/ProjectImport.js +0 -3
  511. package/dist/services/ProjectImport.js.map +1 -1
  512. package/dist/services/ProjectLibrary.d.ts +0 -18
  513. package/dist/services/ProjectLibrary.d.ts.map +1 -1
  514. package/dist/services/ProjectLibrary.js +0 -20
  515. package/dist/services/ProjectLibrary.js.map +1 -1
  516. package/dist/services/ProjectMetadataStore.d.ts +0 -73
  517. package/dist/services/ProjectMetadataStore.d.ts.map +1 -1
  518. package/dist/services/ProjectMetadataStore.js +0 -90
  519. package/dist/services/ProjectMetadataStore.js.map +1 -1
  520. package/dist/services/ProjectPackageManager.d.ts +0 -12
  521. package/dist/services/ProjectPackageManager.d.ts.map +1 -1
  522. package/dist/services/ProjectPackageManager.js +0 -16
  523. package/dist/services/ProjectPackageManager.js.map +1 -1
  524. package/dist/services/ProjectRegistry.d.ts +2 -18
  525. package/dist/services/ProjectRegistry.d.ts.map +1 -1
  526. package/dist/services/ProjectRegistry.js +0 -18
  527. package/dist/services/ProjectRegistry.js.map +1 -1
  528. package/dist/services/ProjectRuntimeService.d.ts +0 -4
  529. package/dist/services/ProjectRuntimeService.d.ts.map +1 -1
  530. package/dist/services/ProjectRuntimeService.js +0 -5
  531. package/dist/services/ProjectRuntimeService.js.map +1 -1
  532. package/dist/services/ProjectScreenshotService.d.ts +0 -5
  533. package/dist/services/ProjectScreenshotService.d.ts.map +1 -1
  534. package/dist/services/ProjectScreenshotService.js +0 -6
  535. package/dist/services/ProjectScreenshotService.js.map +1 -1
  536. package/dist/services/ProjectStorage.d.ts +0 -4
  537. package/dist/services/ProjectStorage.d.ts.map +1 -1
  538. package/dist/services/ProjectStorage.js +0 -4
  539. package/dist/services/ProjectStorage.js.map +1 -1
  540. package/dist/services/PrototypeBuildService.d.ts +1 -23
  541. package/dist/services/PrototypeBuildService.d.ts.map +1 -1
  542. package/dist/services/PrototypeBuildService.js +6 -31
  543. package/dist/services/PrototypeBuildService.js.map +1 -1
  544. package/dist/services/PrototypeDeployService.d.ts +0 -20
  545. package/dist/services/PrototypeDeployService.d.ts.map +1 -1
  546. package/dist/services/PrototypeDeployService.js +1 -24
  547. package/dist/services/PrototypeDeployService.js.map +1 -1
  548. package/dist/services/RequestAuthContext.d.ts +0 -5
  549. package/dist/services/RequestAuthContext.d.ts.map +1 -1
  550. package/dist/services/RequestAuthContext.js +0 -5
  551. package/dist/services/RequestAuthContext.js.map +1 -1
  552. package/dist/services/SessionBridgeService.d.ts.map +1 -1
  553. package/dist/services/SessionBridgeService.js +0 -2
  554. package/dist/services/SessionBridgeService.js.map +1 -1
  555. package/dist/services/SessionService.d.ts +0 -4
  556. package/dist/services/SessionService.d.ts.map +1 -1
  557. package/dist/services/SessionService.js +1 -22
  558. package/dist/services/SessionService.js.map +1 -1
  559. package/dist/services/StaticFileService.d.ts +0 -9
  560. package/dist/services/StaticFileService.d.ts.map +1 -1
  561. package/dist/services/StaticFileService.js +0 -11
  562. package/dist/services/StaticFileService.js.map +1 -1
  563. package/dist/services/StaticLibraryPreviews.d.ts +0 -3
  564. package/dist/services/StaticLibraryPreviews.d.ts.map +1 -1
  565. package/dist/services/StaticLibraryPreviews.js +0 -3
  566. package/dist/services/StaticLibraryPreviews.js.map +1 -1
  567. package/dist/services/StaticPreviewServer.d.ts +0 -16
  568. package/dist/services/StaticPreviewServer.d.ts.map +1 -1
  569. package/dist/services/StaticPreviewServer.js +2 -28
  570. package/dist/services/StaticPreviewServer.js.map +1 -1
  571. package/dist/services/SupabaseAuthService.d.ts +0 -11
  572. package/dist/services/SupabaseAuthService.d.ts.map +1 -1
  573. package/dist/services/SupabaseAuthService.js +0 -11
  574. package/dist/services/SupabaseAuthService.js.map +1 -1
  575. package/dist/services/SupportTicketService.d.ts +0 -4
  576. package/dist/services/SupportTicketService.d.ts.map +1 -1
  577. package/dist/services/SupportTicketService.js +0 -4
  578. package/dist/services/SupportTicketService.js.map +1 -1
  579. package/dist/services/TelemetryService.d.ts +9 -182
  580. package/dist/services/TelemetryService.d.ts.map +1 -1
  581. package/dist/services/TelemetryService.js +11 -195
  582. package/dist/services/TelemetryService.js.map +1 -1
  583. package/dist/services/TreeStore.d.ts +0 -72
  584. package/dist/services/TreeStore.d.ts.map +1 -1
  585. package/dist/services/TreeStore.js +0 -93
  586. package/dist/services/TreeStore.js.map +1 -1
  587. package/dist/services/VariantGenerationService.d.ts +1 -32
  588. package/dist/services/VariantGenerationService.d.ts.map +1 -1
  589. package/dist/services/VariantGenerationService.js +36 -66
  590. package/dist/services/VariantGenerationService.js.map +1 -1
  591. package/dist/services/VariantHistoryService.d.ts +12 -114
  592. package/dist/services/VariantHistoryService.d.ts.map +1 -1
  593. package/dist/services/VariantHistoryService.js +56 -144
  594. package/dist/services/VariantHistoryService.js.map +1 -1
  595. package/dist/services/VariantRunService.d.ts +6 -31
  596. package/dist/services/VariantRunService.d.ts.map +1 -1
  597. package/dist/services/VariantRunService.js +86 -37
  598. package/dist/services/VariantRunService.js.map +1 -1
  599. package/dist/services/VariantsRuntime.d.ts +0 -3
  600. package/dist/services/VariantsRuntime.d.ts.map +1 -1
  601. package/dist/services/VariantsRuntime.js +2 -5
  602. package/dist/services/VariantsRuntime.js.map +1 -1
  603. package/dist/services/WorktreeManager.d.ts +0 -217
  604. package/dist/services/WorktreeManager.d.ts.map +1 -1
  605. package/dist/services/WorktreeManager.js +3 -321
  606. package/dist/services/WorktreeManager.js.map +1 -1
  607. package/dist/services/accessTokenRefresh.d.ts +0 -25
  608. package/dist/services/accessTokenRefresh.d.ts.map +1 -1
  609. package/dist/services/accessTokenRefresh.js +0 -25
  610. package/dist/services/accessTokenRefresh.js.map +1 -1
  611. package/dist/services/adapters/TailwindTokenAdapter.d.ts +0 -29
  612. package/dist/services/adapters/TailwindTokenAdapter.d.ts.map +1 -1
  613. package/dist/services/adapters/TailwindTokenAdapter.js +1 -46
  614. package/dist/services/adapters/TailwindTokenAdapter.js.map +1 -1
  615. package/dist/services/createAgentVariantsOrchestrator.d.ts +0 -18
  616. package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
  617. package/dist/services/createAgentVariantsOrchestrator.js +0 -22
  618. package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
  619. package/dist/services/extractors/CSSVariableExtractor.d.ts +0 -25
  620. package/dist/services/extractors/CSSVariableExtractor.d.ts.map +1 -1
  621. package/dist/services/extractors/CSSVariableExtractor.js +1 -42
  622. package/dist/services/extractors/CSSVariableExtractor.js.map +1 -1
  623. package/dist/services/historyRoots.d.ts +0 -12
  624. package/dist/services/historyRoots.d.ts.map +1 -1
  625. package/dist/services/historyRoots.js +0 -13
  626. package/dist/services/historyRoots.js.map +1 -1
  627. package/dist/services/libraryErrors.d.ts +0 -1
  628. package/dist/services/libraryErrors.d.ts.map +1 -1
  629. package/dist/services/libraryErrors.js +0 -1
  630. package/dist/services/libraryErrors.js.map +1 -1
  631. package/dist/services/pendingLogin.d.ts +0 -13
  632. package/dist/services/pendingLogin.d.ts.map +1 -1
  633. package/dist/services/pendingLogin.js +0 -3
  634. package/dist/services/pendingLogin.js.map +1 -1
  635. package/dist/services/profiles/DesignProfiles.d.ts +446 -0
  636. package/dist/services/profiles/DesignProfiles.d.ts.map +1 -0
  637. package/dist/services/profiles/DesignProfiles.js +552 -0
  638. package/dist/services/profiles/DesignProfiles.js.map +1 -0
  639. package/dist/services/profiles/MemoryModelService.d.ts +14 -0
  640. package/dist/services/profiles/MemoryModelService.d.ts.map +1 -0
  641. package/dist/services/profiles/MemoryModelService.js +113 -0
  642. package/dist/services/profiles/MemoryModelService.js.map +1 -0
  643. package/dist/services/profiles/MemoryRuntime.d.ts +26 -0
  644. package/dist/services/profiles/MemoryRuntime.d.ts.map +1 -0
  645. package/dist/services/profiles/MemoryRuntime.js +192 -0
  646. package/dist/services/profiles/MemoryRuntime.js.map +1 -0
  647. package/dist/services/profiles/ProfileAgent.d.ts +20 -0
  648. package/dist/services/profiles/ProfileAgent.d.ts.map +1 -0
  649. package/dist/services/profiles/ProfileAgent.js +196 -0
  650. package/dist/services/profiles/ProfileAgent.js.map +1 -0
  651. package/dist/services/profiles/ProfileAnalysis.d.ts +23 -0
  652. package/dist/services/profiles/ProfileAnalysis.d.ts.map +1 -0
  653. package/dist/services/profiles/ProfileAnalysis.js +114 -0
  654. package/dist/services/profiles/ProfileAnalysis.js.map +1 -0
  655. package/dist/services/profiles/ProfileImportSchedule.d.ts +15 -0
  656. package/dist/services/profiles/ProfileImportSchedule.d.ts.map +1 -0
  657. package/dist/services/profiles/ProfileImportSchedule.js +40 -0
  658. package/dist/services/profiles/ProfileImportSchedule.js.map +1 -0
  659. package/dist/services/profiles/ProfileImports.d.ts +47 -0
  660. package/dist/services/profiles/ProfileImports.d.ts.map +1 -0
  661. package/dist/services/profiles/ProfileImports.js +248 -0
  662. package/dist/services/profiles/ProfileImports.js.map +1 -0
  663. package/dist/services/profiles/ProfileIndex.d.ts +18 -0
  664. package/dist/services/profiles/ProfileIndex.d.ts.map +1 -0
  665. package/dist/services/profiles/ProfileIndex.js +119 -0
  666. package/dist/services/profiles/ProfileIndex.js.map +1 -0
  667. package/dist/services/profiles/ProfileMedia.d.ts +10 -0
  668. package/dist/services/profiles/ProfileMedia.d.ts.map +1 -0
  669. package/dist/services/profiles/ProfileMedia.js +76 -0
  670. package/dist/services/profiles/ProfileMedia.js.map +1 -0
  671. package/dist/services/profiles/ProfilePreparation.d.ts +17 -0
  672. package/dist/services/profiles/ProfilePreparation.d.ts.map +1 -0
  673. package/dist/services/profiles/ProfilePreparation.js +214 -0
  674. package/dist/services/profiles/ProfilePreparation.js.map +1 -0
  675. package/dist/services/profiles/ProfileVariants.d.ts +33 -0
  676. package/dist/services/profiles/ProfileVariants.d.ts.map +1 -0
  677. package/dist/services/profiles/ProfileVariants.js +129 -0
  678. package/dist/services/profiles/ProfileVariants.js.map +1 -0
  679. package/dist/services/profiles/analysisBatch.d.ts +53 -0
  680. package/dist/services/profiles/analysisBatch.d.ts.map +1 -0
  681. package/dist/services/profiles/analysisBatch.js +86 -0
  682. package/dist/services/profiles/analysisBatch.js.map +1 -0
  683. package/dist/services/profiles/boardPage.d.ts +12 -0
  684. package/dist/services/profiles/boardPage.d.ts.map +1 -0
  685. package/dist/services/profiles/boardPage.js +156 -0
  686. package/dist/services/profiles/boardPage.js.map +1 -0
  687. package/dist/services/profiles/engineAccess.d.ts +2 -0
  688. package/dist/services/profiles/engineAccess.d.ts.map +1 -0
  689. package/dist/services/profiles/engineAccess.js +55 -0
  690. package/dist/services/profiles/engineAccess.js.map +1 -0
  691. package/dist/services/profiles/memoryComponents.d.ts +7 -0
  692. package/dist/services/profiles/memoryComponents.d.ts.map +1 -0
  693. package/dist/services/profiles/memoryComponents.js +105 -0
  694. package/dist/services/profiles/memoryComponents.js.map +1 -0
  695. package/dist/services/profiles/modelContract.d.ts +14 -0
  696. package/dist/services/profiles/modelContract.d.ts.map +1 -0
  697. package/dist/services/profiles/modelContract.js +124 -0
  698. package/dist/services/profiles/modelContract.js.map +1 -0
  699. package/dist/services/profiles/nativeImages.d.ts +3 -0
  700. package/dist/services/profiles/nativeImages.d.ts.map +1 -0
  701. package/dist/services/profiles/nativeImages.js +72 -0
  702. package/dist/services/profiles/nativeImages.js.map +1 -0
  703. package/dist/services/profiles/profileAccount.d.ts +4 -0
  704. package/dist/services/profiles/profileAccount.d.ts.map +1 -0
  705. package/dist/services/profiles/profileAccount.js +21 -0
  706. package/dist/services/profiles/profileAccount.js.map +1 -0
  707. package/dist/services/profiles/profileContext.d.ts +18 -0
  708. package/dist/services/profiles/profileContext.d.ts.map +1 -0
  709. package/dist/services/profiles/profileContext.js +189 -0
  710. package/dist/services/profiles/profileContext.js.map +1 -0
  711. package/dist/services/profiles/profileEvidence.d.ts +3 -0
  712. package/dist/services/profiles/profileEvidence.d.ts.map +1 -0
  713. package/dist/services/profiles/profileEvidence.js +15 -0
  714. package/dist/services/profiles/profileEvidence.js.map +1 -0
  715. package/dist/services/profiles/profileQueries.d.ts +2 -0
  716. package/dist/services/profiles/profileQueries.d.ts.map +1 -0
  717. package/dist/services/profiles/profileQueries.js +23 -0
  718. package/dist/services/profiles/profileQueries.js.map +1 -0
  719. package/dist/services/profiles/profileSelection.d.ts +29 -0
  720. package/dist/services/profiles/profileSelection.d.ts.map +1 -0
  721. package/dist/services/profiles/profileSelection.js +43 -0
  722. package/dist/services/profiles/profileSelection.js.map +1 -0
  723. package/dist/services/profiles/xPage.d.ts +4 -0
  724. package/dist/services/profiles/xPage.d.ts.map +1 -0
  725. package/dist/services/profiles/xPage.js +58 -0
  726. package/dist/services/profiles/xPage.js.map +1 -0
  727. package/dist/services/referenceImages.d.ts +17 -0
  728. package/dist/services/referenceImages.d.ts.map +1 -0
  729. package/dist/services/referenceImages.js +138 -0
  730. package/dist/services/referenceImages.js.map +1 -0
  731. package/dist/services/staticProjectTarget.d.ts +0 -4
  732. package/dist/services/staticProjectTarget.d.ts.map +1 -1
  733. package/dist/services/staticProjectTarget.js +0 -4
  734. package/dist/services/staticProjectTarget.js.map +1 -1
  735. package/dist/services/staticStarter.d.ts +0 -20
  736. package/dist/services/staticStarter.d.ts.map +1 -1
  737. package/dist/services/staticStarter.js +0 -20
  738. package/dist/services/staticStarter.js.map +1 -1
  739. package/dist/services/templates/designCatalog.d.ts +0 -11
  740. package/dist/services/templates/designCatalog.d.ts.map +1 -1
  741. package/dist/services/templates/designCatalog.js +0 -26
  742. package/dist/services/templates/designCatalog.js.map +1 -1
  743. package/dist/services/templates/viteReactTs.d.ts +0 -26
  744. package/dist/services/templates/viteReactTs.d.ts.map +1 -1
  745. package/dist/services/templates/viteReactTs.js +0 -20
  746. package/dist/services/templates/viteReactTs.js.map +1 -1
  747. package/dist/storage/library/BundleMetadataStore.d.ts +0 -16
  748. package/dist/storage/library/BundleMetadataStore.d.ts.map +1 -1
  749. package/dist/storage/library/BundleMetadataStore.js +0 -17
  750. package/dist/storage/library/BundleMetadataStore.js.map +1 -1
  751. package/dist/storage/library/CoordinatorRecords.d.ts +0 -9
  752. package/dist/storage/library/CoordinatorRecords.d.ts.map +1 -1
  753. package/dist/storage/library/CoordinatorRecords.js +0 -9
  754. package/dist/storage/library/CoordinatorRecords.js.map +1 -1
  755. package/dist/storage/library/ProjectPreviewCache.d.ts +0 -4
  756. package/dist/storage/library/ProjectPreviewCache.d.ts.map +1 -1
  757. package/dist/storage/library/ProjectPreviewCache.js +0 -4
  758. package/dist/storage/library/ProjectPreviewCache.js.map +1 -1
  759. package/dist/storage/library/ProjectRecords.d.ts +0 -17
  760. package/dist/storage/library/ProjectRecords.d.ts.map +1 -1
  761. package/dist/storage/library/ProjectRecords.js +0 -17
  762. package/dist/storage/library/ProjectRecords.js.map +1 -1
  763. package/dist/storage/library/database.d.ts +0 -3
  764. package/dist/storage/library/database.d.ts.map +1 -1
  765. package/dist/storage/library/database.js +0 -3
  766. package/dist/storage/library/database.js.map +1 -1
  767. package/dist/storage/library/migrations.d.ts +0 -2
  768. package/dist/storage/library/migrations.d.ts.map +1 -1
  769. package/dist/storage/library/migrations.js +0 -2
  770. package/dist/storage/library/migrations.js.map +1 -1
  771. package/dist/storage/library/sourcePresentation.d.ts +0 -1
  772. package/dist/storage/library/sourcePresentation.d.ts.map +1 -1
  773. package/dist/storage/library/sourcePresentation.js +0 -1
  774. package/dist/storage/library/sourcePresentation.js.map +1 -1
  775. package/dist/storage/profiles/ProfileRecords.d.ts +199 -0
  776. package/dist/storage/profiles/ProfileRecords.d.ts.map +1 -0
  777. package/dist/storage/profiles/ProfileRecords.js +659 -0
  778. package/dist/storage/profiles/ProfileRecords.js.map +1 -0
  779. package/dist/storage/profiles/contextReceipts.d.ts +14 -0
  780. package/dist/storage/profiles/contextReceipts.d.ts.map +1 -0
  781. package/dist/storage/profiles/contextReceipts.js +52 -0
  782. package/dist/storage/profiles/contextReceipts.js.map +1 -0
  783. package/dist/storage/profiles/migrations.d.ts +4 -0
  784. package/dist/storage/profiles/migrations.d.ts.map +1 -0
  785. package/dist/storage/profiles/migrations.js +41 -0
  786. package/dist/storage/profiles/migrations.js.map +1 -0
  787. package/dist/storage/profiles/schema.d.ts +961 -0
  788. package/dist/storage/profiles/schema.d.ts.map +1 -0
  789. package/dist/storage/profiles/schema.js +102 -0
  790. package/dist/storage/profiles/schema.js.map +1 -0
  791. package/dist/storage/project-metadata/ProjectMetadataRecords.d.ts +0 -11
  792. package/dist/storage/project-metadata/ProjectMetadataRecords.d.ts.map +1 -1
  793. package/dist/storage/project-metadata/ProjectMetadataRecords.js +0 -13
  794. package/dist/storage/project-metadata/ProjectMetadataRecords.js.map +1 -1
  795. package/dist/storage/project-metadata/database.d.ts +0 -1
  796. package/dist/storage/project-metadata/database.d.ts.map +1 -1
  797. package/dist/storage/project-metadata/database.js +0 -7
  798. package/dist/storage/project-metadata/database.js.map +1 -1
  799. package/dist/storage/project-metadata/migrations.d.ts +0 -42
  800. package/dist/storage/project-metadata/migrations.d.ts.map +1 -1
  801. package/dist/storage/project-metadata/migrations.js +0 -41
  802. package/dist/storage/project-metadata/migrations.js.map +1 -1
  803. package/dist/types/account.d.ts +0 -1
  804. package/dist/types/account.d.ts.map +1 -1
  805. package/dist/types/change-request-types.d.ts +5 -167
  806. package/dist/types/change-request-types.d.ts.map +1 -1
  807. package/dist/types/change-types.d.ts +0 -1
  808. package/dist/types/change-types.d.ts.map +1 -1
  809. package/dist/types/change-types.js +0 -1
  810. package/dist/types/change-types.js.map +1 -1
  811. package/dist/types/design-profile.d.ts +570 -0
  812. package/dist/types/design-profile.d.ts.map +1 -0
  813. package/dist/types/design-profile.js +127 -0
  814. package/dist/types/design-profile.js.map +1 -0
  815. package/dist/types/project-library.d.ts +0 -1
  816. package/dist/types/project-library.d.ts.map +1 -1
  817. package/dist/types/style-manipulation-types.d.ts +0 -69
  818. package/dist/types/style-manipulation-types.d.ts.map +1 -1
  819. package/dist/types/style-manipulation-types.js +0 -26
  820. package/dist/types/style-manipulation-types.js.map +1 -1
  821. package/dist/types/token-types.d.ts +0 -30
  822. package/dist/types/token-types.d.ts.map +1 -1
  823. package/dist/types/token-types.js +0 -1
  824. package/dist/types/token-types.js.map +1 -1
  825. package/dist/types/variant-history.d.ts +3 -39
  826. package/dist/types/variant-history.d.ts.map +1 -1
  827. package/dist/types/variant-reference.d.ts +46 -0
  828. package/dist/types/variant-reference.d.ts.map +1 -0
  829. package/dist/types/variant-reference.js +58 -0
  830. package/dist/types/variant-reference.js.map +1 -0
  831. package/dist/types/x-bookmarks.d.ts +352 -0
  832. package/dist/types/x-bookmarks.d.ts.map +1 -0
  833. package/dist/types/x-bookmarks.js +56 -0
  834. package/dist/types/x-bookmarks.js.map +1 -0
  835. package/dist/utils/ProviderRateLimit.d.ts +7 -0
  836. package/dist/utils/ProviderRateLimit.d.ts.map +1 -0
  837. package/dist/utils/ProviderRateLimit.js +36 -0
  838. package/dist/utils/ProviderRateLimit.js.map +1 -0
  839. package/dist/utils/branchNames.d.ts +0 -1
  840. package/dist/utils/branchNames.d.ts.map +1 -1
  841. package/dist/utils/branchNames.js +0 -2
  842. package/dist/utils/branchNames.js.map +1 -1
  843. package/dist/utils/cloneOrCopyDirSync.d.ts +0 -12
  844. package/dist/utils/cloneOrCopyDirSync.d.ts.map +1 -1
  845. package/dist/utils/cloneOrCopyDirSync.js +0 -16
  846. package/dist/utils/cloneOrCopyDirSync.js.map +1 -1
  847. package/dist/utils/devServerCommand.d.ts +0 -23
  848. package/dist/utils/devServerCommand.d.ts.map +1 -1
  849. package/dist/utils/devServerCommand.js +0 -24
  850. package/dist/utils/devServerCommand.js.map +1 -1
  851. package/dist/utils/devServerError.d.ts +0 -16
  852. package/dist/utils/devServerError.d.ts.map +1 -1
  853. package/dist/utils/devServerError.js +0 -17
  854. package/dist/utils/devServerError.js.map +1 -1
  855. package/dist/utils/displayLocale.d.ts +0 -2
  856. package/dist/utils/displayLocale.d.ts.map +1 -1
  857. package/dist/utils/displayLocale.js +0 -2
  858. package/dist/utils/displayLocale.js.map +1 -1
  859. package/dist/utils/elementFileHintSignals.d.ts +0 -5
  860. package/dist/utils/elementFileHintSignals.d.ts.map +1 -1
  861. package/dist/utils/elementFileHintSignals.js +0 -5
  862. package/dist/utils/elementFileHintSignals.js.map +1 -1
  863. package/dist/utils/formatElementTargetingContext.d.ts +0 -6
  864. package/dist/utils/formatElementTargetingContext.d.ts.map +1 -1
  865. package/dist/utils/formatElementTargetingContext.js +3 -9
  866. package/dist/utils/formatElementTargetingContext.js.map +1 -1
  867. package/dist/utils/hostAgentEnv.d.ts +0 -17
  868. package/dist/utils/hostAgentEnv.d.ts.map +1 -1
  869. package/dist/utils/hostAgentEnv.js +0 -17
  870. package/dist/utils/hostAgentEnv.js.map +1 -1
  871. package/dist/utils/htmlDocument.d.ts +0 -5
  872. package/dist/utils/htmlDocument.d.ts.map +1 -1
  873. package/dist/utils/htmlDocument.js +2 -7
  874. package/dist/utils/htmlDocument.js.map +1 -1
  875. package/dist/utils/internalGitIdentity.d.ts +0 -5
  876. package/dist/utils/internalGitIdentity.d.ts.map +1 -1
  877. package/dist/utils/internalGitIdentity.js +0 -5
  878. package/dist/utils/internalGitIdentity.js.map +1 -1
  879. package/dist/utils/logger.d.ts +0 -5
  880. package/dist/utils/logger.d.ts.map +1 -1
  881. package/dist/utils/logger.js +2 -19
  882. package/dist/utils/logger.js.map +1 -1
  883. package/dist/utils/loginShellPath.d.ts +0 -9
  884. package/dist/utils/loginShellPath.d.ts.map +1 -1
  885. package/dist/utils/loginShellPath.js +0 -69
  886. package/dist/utils/loginShellPath.js.map +1 -1
  887. package/dist/utils/loopback.d.ts +0 -1
  888. package/dist/utils/loopback.d.ts.map +1 -1
  889. package/dist/utils/loopback.js +0 -1
  890. package/dist/utils/loopback.js.map +1 -1
  891. package/dist/utils/pid.d.ts +0 -1
  892. package/dist/utils/pid.d.ts.map +1 -1
  893. package/dist/utils/pid.js +0 -1
  894. package/dist/utils/pid.js.map +1 -1
  895. package/dist/utils/portUtils.d.ts +0 -15
  896. package/dist/utils/portUtils.d.ts.map +1 -1
  897. package/dist/utils/portUtils.js +0 -21
  898. package/dist/utils/portUtils.js.map +1 -1
  899. package/dist/utils/queueAccess.d.ts +0 -9
  900. package/dist/utils/queueAccess.d.ts.map +1 -1
  901. package/dist/utils/queueAccess.js +0 -9
  902. package/dist/utils/queueAccess.js.map +1 -1
  903. package/dist/utils/skillWriter.d.ts +0 -17
  904. package/dist/utils/skillWriter.d.ts.map +1 -1
  905. package/dist/utils/skillWriter.js +0 -20
  906. package/dist/utils/skillWriter.js.map +1 -1
  907. package/dist/utils/skills/claude-skill.d.ts +0 -5
  908. package/dist/utils/skills/claude-skill.d.ts.map +1 -1
  909. package/dist/utils/skills/claude-skill.js +0 -5
  910. package/dist/utils/skills/claude-skill.js.map +1 -1
  911. package/dist/utils/skills/cli-guidance.d.ts +1 -9
  912. package/dist/utils/skills/cli-guidance.d.ts.map +1 -1
  913. package/dist/utils/skills/cli-guidance.js +6 -10
  914. package/dist/utils/skills/cli-guidance.js.map +1 -1
  915. package/dist/utils/skills/cursor-rules.d.ts +0 -6
  916. package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
  917. package/dist/utils/skills/cursor-rules.js +0 -6
  918. package/dist/utils/skills/cursor-rules.js.map +1 -1
  919. package/dist/utils/variantPreviewPort.d.ts +0 -3
  920. package/dist/utils/variantPreviewPort.d.ts.map +1 -1
  921. package/dist/utils/variantPreviewPort.js +0 -3
  922. package/dist/utils/variantPreviewPort.js.map +1 -1
  923. package/dist/utils/windowPlacement.d.ts +0 -4
  924. package/dist/utils/windowPlacement.d.ts.map +1 -1
  925. package/dist/utils/windowPlacement.js +0 -4
  926. package/dist/utils/windowPlacement.js.map +1 -1
  927. package/package.json +13 -13
  928. package/scripts/verify-node-version.cjs +0 -3
  929. package/src/ui/dist/assets/{LibraryApp-qbLqcNxM.js → LibraryApp-Bu7hVbt_.js} +1 -1
  930. package/src/ui/dist/assets/main-CHyx_rEa.css +1 -0
  931. package/src/ui/dist/assets/main-CuiPb_rl.js +438 -0
  932. package/src/ui/dist/index.html +2 -2
  933. package/dist/utils/skills/describe-motion-protocol.d.ts +0 -10
  934. package/dist/utils/skills/describe-motion-protocol.d.ts.map +0 -1
  935. package/dist/utils/skills/describe-motion-protocol.js +0 -231
  936. package/dist/utils/skills/describe-motion-protocol.js.map +0 -1
  937. package/src/ui/dist/assets/main-BUZjlAHd.css +0 -1
  938. package/src/ui/dist/assets/main-touv07Dk.js +0 -438
@@ -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,25 +512,22 @@ 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) {
522
+ const paths = new Set();
703
523
  const files = (context?.userContext ?? [])
704
524
  .filter((source) => source.transport === 'file')
525
+ .filter((source) => {
526
+ if (paths.has(source.path))
527
+ return false;
528
+ paths.add(source.path);
529
+ return true;
530
+ })
705
531
  .map((source) => ({
706
532
  path: source.path,
707
533
  ...((source.label ?? source.originalFilename)
@@ -1050,8 +876,6 @@ class AgentVariantsOrchestrator {
1050
876
  if (projectContext.variantContext) {
1051
877
  (0, variantContext_1.writeVariantContextBundle)(projectContext.variantContext);
1052
878
  }
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
879
  const bundle = projectContext.kind === 'fresh'
1056
880
  ? projectContext.variantContext
1057
881
  : undefined;
@@ -1113,9 +937,6 @@ class AgentVariantsOrchestrator {
1113
937
  }
1114
938
  throw error;
1115
939
  }
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
940
  const resources = this.resources.get(args.sessionId);
1120
941
  if (resources) {
1121
942
  const now = Date.now();
@@ -1125,10 +946,6 @@ class AgentVariantsOrchestrator {
1125
946
  }
1126
947
  this.writeLeasedWorkItemBriefings(args.sessionId, result.leasedWorkItems.map((item) => item.id));
1127
948
  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
949
  const decorated = {
1133
950
  ...result,
1134
951
  leasedWorkItems: result.leasedWorkItems.map((item) => {
@@ -1145,7 +962,6 @@ class AgentVariantsOrchestrator {
1145
962
  this.emitChange();
1146
963
  return decorated;
1147
964
  }
1148
- /** @effect Copies caller-supplied context assets into each leased workspace. */
1149
965
  materializeContextAssets(sessionId, items) {
1150
966
  const resources = this.ensureResources(sessionId);
1151
967
  for (const item of items) {
@@ -1166,10 +982,6 @@ class AgentVariantsOrchestrator {
1166
982
  resources.contextAssets.set(item.id, (0, contextAssets_1.materializeContextAssets)({ assets, workspace, previewKind }));
1167
983
  }
1168
984
  }
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
985
  async resolveContextAssetPreviewKind(sessionId) {
1174
986
  const resources = this.ensureResources(sessionId);
1175
987
  try {
@@ -1182,13 +994,6 @@ class AgentVariantsOrchestrator {
1182
994
  log.warn(`Failed to resolve context asset preview kind for ${sessionId}; using dev-server references`, error);
1183
995
  }
1184
996
  }
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
997
  writeLeasedWorkItemBriefings(sessionId, leasedWorkItemIds) {
1193
998
  if (leasedWorkItemIds.length === 0)
1194
999
  return;
@@ -1218,13 +1023,9 @@ class AgentVariantsOrchestrator {
1218
1023
  }
1219
1024
  }
1220
1025
  }
1221
- /** @effect Assigns isolated, server-owned artifact workspaces to leased static work. */
1222
1026
  ensureStaticWorkspaces(sessionId, items) {
1223
1027
  const resources = this.ensureResources(sessionId);
1224
1028
  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
1029
  const provisionStartedAt = Date.now();
1229
1030
  let assignedCount = 0;
1230
1031
  for (const item of items) {
@@ -1271,7 +1072,6 @@ class AgentVariantsOrchestrator {
1271
1072
  });
1272
1073
  }
1273
1074
  }
1274
- /** Reads a completed static artifact while enforcing its assigned directory boundary. */
1275
1075
  readAssignedStaticArtifact(sessionId, workItemId) {
1276
1076
  const workspaceManager = this.resources.get(sessionId)?.workspaceManager;
1277
1077
  if (!workspaceManager) {
@@ -1281,15 +1081,7 @@ class AgentVariantsOrchestrator {
1281
1081
  }
1282
1082
  beginStaticPreviewRefinements(args) {
1283
1083
  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
1084
  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
1085
  const createdWorkItemIds = [];
1294
1086
  for (const target of args.targets) {
1295
1087
  if (seenVariantIds.has(target.variantId))
@@ -1310,9 +1102,6 @@ class AgentVariantsOrchestrator {
1310
1102
  });
1311
1103
  const currentHtml = this.getStaticPreviewHtml(args.sessionId, target.variantId);
1312
1104
  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
1105
  try {
1317
1106
  const refineItem = this.store.createRefineVariantWorkItem({
1318
1107
  sessionId: args.sessionId,
@@ -1327,8 +1116,6 @@ class AgentVariantsOrchestrator {
1327
1116
  createdWorkItemIds.push(refineItem.id);
1328
1117
  }
1329
1118
  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
1119
  if (error instanceof errors_1.AgentVariantsError &&
1333
1120
  error.code === 'PENDING_CHANGE_CONFLICT') {
1334
1121
  const folded = this.store.appendPendingRefineVariantInstruction({
@@ -1338,8 +1125,6 @@ class AgentVariantsOrchestrator {
1338
1125
  fidelity: target.fidelity,
1339
1126
  });
1340
1127
  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
1128
  droppedRefinements.push({
1344
1129
  variantId: target.variantId,
1345
1130
  reason: error.message,
@@ -1359,10 +1144,15 @@ class AgentVariantsOrchestrator {
1359
1144
  }
1360
1145
  continue;
1361
1146
  }
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
1147
  try {
1148
+ const source = this.store.getWorkItemInput(args.sessionId, target.variantId);
1149
+ const additionalContext = target.additionalContext
1150
+ ? (0, variantContext_1.extendVariantContextBundle)({
1151
+ sessionId: args.sessionId,
1152
+ source: source.context,
1153
+ additional: target.additionalContext,
1154
+ })
1155
+ : undefined;
1366
1156
  const forks = this.store.createForkedStaticPreviewWorkItems({
1367
1157
  sessionId: args.sessionId,
1368
1158
  sourceVariantId: target.variantId,
@@ -1375,18 +1165,15 @@ class AgentVariantsOrchestrator {
1375
1165
  targetElement: target.element,
1376
1166
  relevantFiles: target.relevantFiles,
1377
1167
  requestId: target.requestId,
1168
+ additionalContext,
1378
1169
  });
1379
1170
  createdWorkItemIds.push(...forks.map((item) => item.id));
1380
1171
  }
1381
1172
  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
1173
  if (error instanceof errors_1.AgentVariantsError &&
1388
1174
  (error.code === 'PENDING_CHANGE_CONFLICT' ||
1389
- error.code === 'VARIANT_NOT_EDITABLE')) {
1175
+ error.code === 'VARIANT_NOT_EDITABLE' ||
1176
+ error.code === 'SOURCE_CONTEXT_INVALID')) {
1390
1177
  droppedRefinements.push({
1391
1178
  variantId: target.variantId,
1392
1179
  reason: error.message,
@@ -1410,24 +1197,6 @@ class AgentVariantsOrchestrator {
1410
1197
  this.emitChange();
1411
1198
  return { droppedRefinements, createdWorkItemIds };
1412
1199
  }
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
1200
  async adoptPastVariant(args) {
1432
1201
  const { assetBase, hasAssets } = await this.resolveAdoptedStaticPreviewFiles(args.filesDir, args.entryPath);
1433
1202
  const append = this.store.appendAdoptedStaticVariant({
@@ -1435,6 +1204,7 @@ class AgentVariantsOrchestrator {
1435
1204
  source: args.source,
1436
1205
  label: args.label,
1437
1206
  description: args.description,
1207
+ references: args.references,
1438
1208
  runLabel: args.runLabel,
1439
1209
  });
1440
1210
  this.telemetry.trackAgentVariantsRequestStarted?.({
@@ -1445,8 +1215,6 @@ class AgentVariantsOrchestrator {
1445
1215
  requestedCount: 1,
1446
1216
  sourceVariantId: args.source.variantId,
1447
1217
  });
1448
- // Register (or re-register, harmlessly) the static-preview record so the
1449
- // snapshot surfaces the adopted variant as a static_artifact.
1450
1218
  const resources = this.ensureResources(args.sessionId);
1451
1219
  resources.staticPreviews.set(append.workItemId, {
1452
1220
  workItemId: append.workItemId,
@@ -1471,11 +1239,6 @@ class AgentVariantsOrchestrator {
1471
1239
  alreadyAdopted: !append.created,
1472
1240
  };
1473
1241
  }
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
1242
  async bootstrapPastVariantSession(args) {
1480
1243
  const usableSessionId = this.getUsableActiveSessionId();
1481
1244
  if (usableSessionId) {
@@ -1486,6 +1249,7 @@ class AgentVariantsOrchestrator {
1486
1249
  entryPath: args.entryPath,
1487
1250
  label: args.label,
1488
1251
  description: args.description,
1252
+ references: args.references,
1489
1253
  runLabel: args.runLabel,
1490
1254
  });
1491
1255
  return {
@@ -1504,6 +1268,7 @@ class AgentVariantsOrchestrator {
1504
1268
  prompt: args.prompt ?? args.description ?? args.label,
1505
1269
  label: args.label,
1506
1270
  description: args.description,
1271
+ references: args.references,
1507
1272
  runLabel: args.runLabel,
1508
1273
  projectContext: args.projectContext,
1509
1274
  });
@@ -1556,12 +1321,6 @@ class AgentVariantsOrchestrator {
1556
1321
  }
1557
1322
  return { assetBase, hasAssets };
1558
1323
  }
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
1324
  isStaticPreviewVariant(sessionId, workItemId) {
1566
1325
  try {
1567
1326
  return (this.store.getWorkItemKind(sessionId, workItemId) === 'static_preview');
@@ -1570,11 +1329,6 @@ class AgentVariantsOrchestrator {
1570
1329
  return false;
1571
1330
  }
1572
1331
  }
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
1332
  resolveHistoryParentVariant(sessionId, sourceVariantId) {
1579
1333
  if (!sourceVariantId)
1580
1334
  return undefined;
@@ -1641,10 +1395,6 @@ class AgentVariantsOrchestrator {
1641
1395
  workItemCount: 1,
1642
1396
  instructionLength: args.instruction.length,
1643
1397
  });
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
1398
  return this.requestWork({
1649
1399
  sessionId: args.sessionId,
1650
1400
  leaseOwner: args.leaseOwner,
@@ -1657,7 +1407,6 @@ class AgentVariantsOrchestrator {
1657
1407
  getWorkItemInput(sessionId, workItemId) {
1658
1408
  return this.store.getWorkItemInput(sessionId, workItemId);
1659
1409
  }
1660
- /** Returns status after orchestration QA and refinement post-processing. */
1661
1410
  getWorkItemStatus(sessionId, workItemId) {
1662
1411
  return this.store.getWorkItemStatus(sessionId, workItemId);
1663
1412
  }
@@ -1674,16 +1423,10 @@ class AgentVariantsOrchestrator {
1674
1423
  const resources = this.resources.get(sessionId);
1675
1424
  return this.store.getVariants(sessionId).map((variant) => {
1676
1425
  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
1426
  const capturedDiff = resources?.worktrees.get(variant.workItemId)?.diff;
1681
1427
  const changedFilesCount = typeof capturedDiff === 'string' && capturedDiff.length > 0
1682
1428
  ? countDiffFiles(capturedDiff)
1683
1429
  : 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
1430
  const staticPreview = resources?.staticPreviews.get(variant.workItemId) ??
1688
1431
  this.getStaticPreviewByBriefId(sessionId, variant.briefId);
1689
1432
  let preview;
@@ -1694,11 +1437,6 @@ class AgentVariantsOrchestrator {
1694
1437
  };
1695
1438
  }
1696
1439
  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
1440
  try {
1703
1441
  const output = this.store.getWorkItemOutput(sessionId, variant.workItemId);
1704
1442
  if (typeof output?.html === 'string' && output.html.length > 0) {
@@ -1708,9 +1446,7 @@ class AgentVariantsOrchestrator {
1708
1446
  };
1709
1447
  }
1710
1448
  }
1711
- catch {
1712
- /* work item may not exist in edge cases */
1713
- }
1449
+ catch { }
1714
1450
  }
1715
1451
  if (!preview && port) {
1716
1452
  preview = { kind: 'dev_server', port };
@@ -1719,9 +1455,6 @@ class AgentVariantsOrchestrator {
1719
1455
  const isSucceeded = variant.status === 'succeeded';
1720
1456
  const qaFailed = qa?.status === 'failed';
1721
1457
  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
1458
  const previewFailure = resources?.previewFailures.get(variant.workItemId);
1726
1459
  const previewUnavailable = !canView && isSucceeded && previewFailure
1727
1460
  ? {
@@ -1765,36 +1498,19 @@ class AgentVariantsOrchestrator {
1765
1498
  hasSession(sessionId) {
1766
1499
  return this.store.hasSession(sessionId);
1767
1500
  }
1768
- /** Read the projectContext for a session — used by Express routes that
1769
- * build the chip snapshot via `stateForSession`. */
1770
1501
  getProjectContext(sessionId) {
1771
1502
  return this.store.getProjectContext(sessionId);
1772
1503
  }
1773
- /** Resolve a worktree path for a code-gen work item, if provisioned. */
1774
1504
  getWorktreePath(sessionId, workItemId) {
1775
1505
  return this.resources.get(sessionId)?.worktrees.get(workItemId)
1776
1506
  ?.worktreePath;
1777
1507
  }
1778
- /**
1779
- * Resolve the project cwd inside a worktree so subdirectory projects run
1780
- * from the same repo-relative location.
1781
- */
1782
1508
  getProjectCwdInWorktree(worktreePath) {
1783
1509
  return this.worktrees.getProjectCwdInWorktree(worktreePath);
1784
1510
  }
1785
- /** Resolve the dev server port for a code-gen work item, if running. */
1786
1511
  getDevServerPort(sessionId, workItemId) {
1787
1512
  return this.resources.get(sessionId)?.worktrees.get(workItemId)?.port;
1788
1513
  }
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
1514
  async restoreVariantPreview(sessionId, workItemId, options = {}) {
1799
1515
  const resources = this.resources.get(sessionId);
1800
1516
  const record = resources?.worktrees.get(workItemId);
@@ -1836,10 +1552,6 @@ class AgentVariantsOrchestrator {
1836
1552
  record.previewRestoration = undefined;
1837
1553
  }
1838
1554
  }
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
1555
  resolveDevServerPortForPreview(sessionId, workItemId) {
1844
1556
  const port = this.getDevServerPort(sessionId, workItemId);
1845
1557
  if (typeof port === 'number') {
@@ -1847,14 +1559,6 @@ class AgentVariantsOrchestrator {
1847
1559
  }
1848
1560
  return port;
1849
1561
  }
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
1562
  getVariantWorkItemKind(sessionId, workItemId) {
1859
1563
  try {
1860
1564
  return this.store.getWorkItemKind(sessionId, workItemId);
@@ -1864,9 +1568,6 @@ class AgentVariantsOrchestrator {
1864
1568
  }
1865
1569
  }
1866
1570
  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
1571
  const preview = this.resources
1871
1572
  .get(sessionId)
1872
1573
  ?.staticPreviews.get(workItemId);
@@ -1876,13 +1577,8 @@ class AgentVariantsOrchestrator {
1876
1577
  if (fromDisk.length > 0)
1877
1578
  return fromDisk;
1878
1579
  }
1879
- catch {
1880
- // fall through to the work-item output fallback below
1881
- }
1580
+ catch { }
1882
1581
  }
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
1582
  try {
1887
1583
  const output = this.store.getWorkItemOutput(sessionId, workItemId);
1888
1584
  return typeof output?.html === 'string' && output.html.length > 0
@@ -1893,38 +1589,20 @@ class AgentVariantsOrchestrator {
1893
1589
  return undefined;
1894
1590
  }
1895
1591
  }
1896
- /** Resolve the DESIGN.md markdown behind an artifact link. */
1897
1592
  getDesignContextMarkdown(sessionId, artifactId) {
1898
1593
  const artifact = findDesignContextArtifact(this.store.getProjectContext(sessionId), artifactId);
1899
1594
  return artifact?.content;
1900
1595
  }
1901
- /** Build the rendered DesignMD document for an artifact link. */
1902
1596
  getDesignContextViewerHtml(sessionId, artifactId) {
1903
1597
  const artifact = findDesignContextArtifact(this.store.getProjectContext(sessionId), artifactId);
1904
1598
  return artifact ? buildDesignContextViewerDocument(artifact) : undefined;
1905
1599
  }
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
1600
  hasStaticPreviewAssets(sessionId, workItemId) {
1914
1601
  const record = this.resources
1915
1602
  .get(sessionId)
1916
1603
  ?.staticPreviews.get(workItemId);
1917
1604
  return Boolean(record?.hasAssets);
1918
1605
  }
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
1606
  resolveStaticPreviewAssetPath(sessionId, workItemId, requestedPath) {
1929
1607
  const record = this.resources
1930
1608
  .get(sessionId)
@@ -1933,12 +1611,6 @@ class AgentVariantsOrchestrator {
1933
1611
  return undefined;
1934
1612
  if (!requestedPath || requestedPath.length === 0)
1935
1613
  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
1614
  return (resolveAssetWithinBase(record.assetBase, requestedPath) ??
1943
1615
  (record.assetFallbackBase
1944
1616
  ? resolveAssetWithinBase(record.assetFallbackBase, requestedPath)
@@ -1955,7 +1627,6 @@ class AgentVariantsOrchestrator {
1955
1627
  const safeWorkItemId = encodeURIComponent(workItemId);
1956
1628
  return `/api/variants/${safeSessionId}/static/${safeWorkItemId}`;
1957
1629
  }
1958
- // --- Mutation wrappers (state + side effects) ---------------------------
1959
1630
  async approve(args) {
1960
1631
  const result = this.store.approve(args);
1961
1632
  const resources = this.ensureResources(args.sessionId);
@@ -1976,11 +1647,6 @@ class AgentVariantsOrchestrator {
1976
1647
  workItemIds,
1977
1648
  });
1978
1649
  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
1650
  try {
1985
1651
  if (projectContext.kind === 'existing') {
1986
1652
  await this.resolveContextAssetPreviewKind(args.sessionId);
@@ -1994,50 +1660,19 @@ class AgentVariantsOrchestrator {
1994
1660
  }
1995
1661
  return result;
1996
1662
  }
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
1663
  async startUnified(args) {
1664
+ args.assertContext?.();
2016
1665
  const count = args.briefs?.length ?? args.count ?? contracts_1.DEFAULT_VARIANT_COUNT;
2017
1666
  const projectContext = args.projectContext ?? {
2018
1667
  kind: 'existing',
2019
1668
  };
2020
1669
  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
1670
  const isSourceGrounded = projectContext.kind === 'fresh' &&
2031
1671
  Boolean(projectContext.variantContext) &&
2032
1672
  !args.briefs?.length;
2033
1673
  if (isSourceGrounded) {
2034
1674
  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
1675
  }
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
1676
  const appendSessionId = args.allowAccumulate &&
2042
1677
  projectContext.kind === 'existing' &&
2043
1678
  projectContext.projectPath
@@ -2075,8 +1710,6 @@ class AgentVariantsOrchestrator {
2075
1710
  };
2076
1711
  const { createdWorkItemIds } = this.store.appendCodeGenVariants({
2077
1712
  ...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
1713
  ...(args.sourceVariantId
2081
1714
  ? { sourceVariantId: args.sourceVariantId }
2082
1715
  : {}),
@@ -2115,8 +1748,6 @@ class AgentVariantsOrchestrator {
2115
1748
  projectContext,
2116
1749
  runLabel: args.runLabel,
2117
1750
  ...(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
1751
  hasPreparedBriefs: true,
2121
1752
  ...(args.sessionId ? { sessionId: args.sessionId } : {}),
2122
1753
  });
@@ -2147,18 +1778,11 @@ class AgentVariantsOrchestrator {
2147
1778
  });
2148
1779
  sessionId = proposeResult.sessionId;
2149
1780
  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
1781
  variantIds =
2156
1782
  projectContext.kind === 'fresh'
2157
1783
  ? this.store.getVariants(sessionId).map((v) => v.workItemId)
2158
1784
  : approveResult.codeGenWorkItemIds;
2159
1785
  }
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
1786
  if (args.requestId) {
2163
1787
  this.store.assignVariantRequestId(sessionId, variantIds, args.requestId);
2164
1788
  }
@@ -2188,12 +1812,17 @@ class AgentVariantsOrchestrator {
2188
1812
  let leaseId;
2189
1813
  let leaseTtlMs;
2190
1814
  let leasedWorkItems;
1815
+ try {
1816
+ args.assertContext?.();
1817
+ }
1818
+ catch (error) {
1819
+ await Promise.all(variantIds.map((variantId) => this.cancelVariant({ sessionId, variantId })));
1820
+ throw error;
1821
+ }
2191
1822
  if (args.leaseOwner) {
2192
1823
  const lease = this.requestWork({
2193
1824
  sessionId,
2194
1825
  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
1826
  ...(appendSessionId ? { workItemIds: variantIds } : {}),
2198
1827
  });
2199
1828
  leaseId = lease.leaseId;
@@ -2209,15 +1838,6 @@ class AgentVariantsOrchestrator {
2209
1838
  leasedWorkItems,
2210
1839
  };
2211
1840
  }
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
1841
  buildUnifiedBriefs(args) {
2222
1842
  const briefId = (i) => args.uniqueBriefIds ? `v-${(0, crypto_1.randomUUID)().slice(0, 8)}` : `v${i + 1}`;
2223
1843
  const runLabel = args.runLabel?.trim() || (0, runLabel_1.deriveRunLabel)(args.prompt);
@@ -2247,13 +1867,6 @@ class AgentVariantsOrchestrator {
2247
1867
  body: synthesizeUnifiedBriefBody(args.prompt, i + 1, args.count),
2248
1868
  }, i));
2249
1869
  }
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
1870
  getAppendableExistingSessionId(projectPath) {
2258
1871
  const sessionId = this.activeSessionId;
2259
1872
  if (!sessionId || !this.store.hasSession(sessionId))
@@ -2268,7 +1881,6 @@ class AgentVariantsOrchestrator {
2268
1881
  return null;
2269
1882
  return sessionId;
2270
1883
  }
2271
- /** @effect Registers a provisioned git worktree with runtime and workspace state. */
2272
1884
  async registerWorktreeWorkspace(resources, record) {
2273
1885
  let projectPath = record.worktreePath;
2274
1886
  try {
@@ -2284,15 +1896,6 @@ class AgentVariantsOrchestrator {
2284
1896
  projectPath,
2285
1897
  });
2286
1898
  }
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
1899
  async withProvisioningTelemetry(args, run) {
2297
1900
  const startedAt = Date.now();
2298
1901
  this.telemetry.track('agent_variants.provisioning_started', {
@@ -2347,11 +1950,6 @@ class AgentVariantsOrchestrator {
2347
1950
  })));
2348
1951
  });
2349
1952
  }
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
1953
  async provisionForkedFromVariantWorktrees(sessionId, sourceVariantId, workItemIds) {
2356
1954
  if (workItemIds.length === 0)
2357
1955
  return;
@@ -2359,13 +1957,14 @@ class AgentVariantsOrchestrator {
2359
1957
  if (!sourcePath) {
2360
1958
  throw new errors_1.AgentVariantsError('VARIANT_NOT_EDITABLE', `Cannot fork from variant ${sourceVariantId}: no worktree path`);
2361
1959
  }
2362
- if (!this.worktrees.forkWorktreesFrom) {
1960
+ const forkWorktreesFrom = this.worktrees.forkWorktreesFrom?.bind(this.worktrees);
1961
+ if (!forkWorktreesFrom) {
2363
1962
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'worktreeManager does not implement forkWorktreesFrom');
2364
1963
  }
2365
1964
  await this.withProvisioningTelemetry({ sessionId, kind: 'forked_variant', variantCount: workItemIds.length }, async () => {
2366
1965
  const resources = this.ensureResources(sessionId);
2367
1966
  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);
1967
+ const paths = await withProvisionTimeout(forkWorktreesFrom(sourcePath, sessionId, workItemIds.length, instanceKeyPrefix), this.provisionTimeoutMs);
2369
1968
  await Promise.all(workItemIds.map((id, index) => this.registerWorktreeWorkspace(resources, {
2370
1969
  workItemId: id,
2371
1970
  worktreePath: paths[index],
@@ -2373,15 +1972,7 @@ class AgentVariantsOrchestrator {
2373
1972
  });
2374
1973
  }
2375
1974
  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
1975
  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
1976
  if (this.store.hasSession(args.sessionId) &&
2386
1977
  this.store.isWorkItemAborted(args.sessionId, args.workItemId)) {
2387
1978
  return this.store.reportComplete(args);
@@ -2405,9 +1996,6 @@ class AgentVariantsOrchestrator {
2405
1996
  output: this.readAssignedStaticArtifact(args.sessionId, args.workItemId),
2406
1997
  }
2407
1998
  : 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
1999
  if (resolvedArgs.status === 'succeeded' &&
2412
2000
  this.store.hasSession(args.sessionId) &&
2413
2001
  (workItemKind === 'static_preview' ||
@@ -2425,27 +2013,15 @@ class AgentVariantsOrchestrator {
2425
2013
  }
2426
2014
  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
2015
  }
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
2016
  const qaStartedAt = Date.now();
2432
2017
  const qaEval = workItemKind === 'refine_variant'
2433
2018
  ? null
2434
2019
  : await this.evaluateQaForReport(resolvedArgs);
2435
2020
  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
2021
  if (qaEval?.decision === 'retry') {
2439
2022
  return this.handleQaRegenRetry(resolvedArgs, qaEval.qa);
2440
2023
  }
2441
2024
  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
2025
  if (workItemKind === 'refine_variant' &&
2450
2026
  effectiveArgs.status === 'succeeded') {
2451
2027
  try {
@@ -2492,9 +2068,6 @@ class AgentVariantsOrchestrator {
2492
2068
  throw error;
2493
2069
  }
2494
2070
  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
2071
  if (effectiveArgs.status === 'succeeded' ||
2499
2072
  effectiveArgs.status === 'failed' ||
2500
2073
  effectiveArgs.status === 'cancelled') {
@@ -2503,11 +2076,8 @@ class AgentVariantsOrchestrator {
2503
2076
  const durationMs = leasedAt !== undefined ? Date.now() - leasedAt : null;
2504
2077
  const approveStartedAt = resources?.approveStartedAt;
2505
2078
  const approveToCompleteMs = approveStartedAt !== undefined ? Date.now() - approveStartedAt : null;
2506
- // Byte size of generated output for HTML vs full-stack comparison.
2507
2079
  const outputBytes = estimateOutputBytes(effectiveArgs.output);
2508
2080
  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
2081
  const mode = workItemKind !== undefined && isImplementationWorkItemKind(workItemKind)
2512
2082
  ? this.store.isVaryForkWorkItem(args.sessionId, args.workItemId)
2513
2083
  ? 'vary'
@@ -2523,15 +2093,11 @@ class AgentVariantsOrchestrator {
2523
2093
  approveToCompleteMs,
2524
2094
  kind: workItemKind ?? null,
2525
2095
  mode,
2526
- // Phase split of `durationMs`: agent work vs server-side gating.
2527
2096
  leaseToReportMs: leasedAt !== undefined ? reportReceivedAt - leasedAt : null,
2528
2097
  reportProcessingMs: Date.now() - reportReceivedAt,
2529
2098
  qaMs,
2530
2099
  hasError: Boolean(effectiveArgs.error),
2531
2100
  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
2101
  errorMessage: effectiveArgs.error?.message ?? null,
2536
2102
  errorApiStatus: effectiveArgs.error?.apiErrorStatus ?? null,
2537
2103
  isScaffold: resources?.scaffoldBaseWorkItemId === args.workItemId,
@@ -2617,10 +2183,6 @@ class AgentVariantsOrchestrator {
2617
2183
  log.error(`handleSucceededReport failed for ${args.sessionId}/${args.workItemId}`, err);
2618
2184
  });
2619
2185
  }
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
2186
  return result;
2625
2187
  }
2626
2188
  async cancel(args) {
@@ -2651,13 +2213,6 @@ class AgentVariantsOrchestrator {
2651
2213
  });
2652
2214
  return result;
2653
2215
  }
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
2216
  async cancelVariant(args) {
2662
2217
  const result = this.store.cancelWorkItem({
2663
2218
  sessionId: args.sessionId,
@@ -2687,12 +2242,6 @@ class AgentVariantsOrchestrator {
2687
2242
  alreadyTerminal: result.alreadyTerminal,
2688
2243
  };
2689
2244
  }
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
2245
  async removeVariant(args) {
2697
2246
  const result = this.store.removeWorkItem({
2698
2247
  sessionId: args.sessionId,
@@ -2720,13 +2269,6 @@ class AgentVariantsOrchestrator {
2720
2269
  alreadyRemoved: result.alreadyRemoved,
2721
2270
  };
2722
2271
  }
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
2272
  async renameVariant(args) {
2731
2273
  const result = this.store.renameWorkItem({
2732
2274
  sessionId: args.sessionId,
@@ -2737,7 +2279,6 @@ class AgentVariantsOrchestrator {
2737
2279
  source: 'mcp',
2738
2280
  sessionId: args.sessionId,
2739
2281
  variantId: args.variantId,
2740
- // Telemetry policy: never the raw agent/user label text, only its length.
2741
2282
  labelLength: args.label.length,
2742
2283
  sessionStage: result.sessionStage,
2743
2284
  });
@@ -2752,10 +2293,6 @@ class AgentVariantsOrchestrator {
2752
2293
  sessionStage: result.sessionStage,
2753
2294
  };
2754
2295
  }
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
2296
  async renameRun(args) {
2760
2297
  const result = this.store.renameRun({
2761
2298
  sessionId: args.sessionId,
@@ -2766,7 +2303,6 @@ class AgentVariantsOrchestrator {
2766
2303
  this.telemetry.track('agent_variants.run_renamed', {
2767
2304
  source: 'mcp',
2768
2305
  sessionId: args.sessionId,
2769
- // Telemetry policy: never the raw label text, only its length.
2770
2306
  runLabelLength: args.label.length,
2771
2307
  renamedCount: result.workItemIds.length,
2772
2308
  sessionStage: result.sessionStage,
@@ -2785,18 +2321,7 @@ class AgentVariantsOrchestrator {
2785
2321
  sessionStage: result.sessionStage,
2786
2322
  };
2787
2323
  }
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
2324
  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
2325
  const prior = this.inflightCommits.get(args.sessionId);
2801
2326
  const run = (async () => {
2802
2327
  if (prior) {
@@ -2825,17 +2350,8 @@ class AgentVariantsOrchestrator {
2825
2350
  }
2826
2351
  }
2827
2352
  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
2353
  const existingPick = this.store.getVariantPick(args.sessionId);
2833
2354
  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
2355
  const projectContext = this.store.getProjectContext(args.sessionId);
2840
2356
  let historyProjectPath;
2841
2357
  if (projectContext.kind === 'fresh') {
@@ -2861,9 +2377,6 @@ class AgentVariantsOrchestrator {
2861
2377
  log.warn(`persistVariantHistoryAtCommit (duplicate retry) failed for session ${args.sessionId}`, err);
2862
2378
  });
2863
2379
  }
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
2380
  const lingering = this.lingeringCommittedDevServers.get(args.sessionId);
2868
2381
  const live = this.resources.get(args.sessionId)?.committedDevServer;
2869
2382
  const replayPort = lingering?.port ?? live?.port;
@@ -2898,19 +2411,9 @@ class AgentVariantsOrchestrator {
2898
2411
  let envelopeDestination;
2899
2412
  let changedFilesCount;
2900
2413
  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
2414
  let committedPreviewPort;
2906
2415
  if (projectContext.kind === 'fresh') {
2907
2416
  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
2417
  let realDestination;
2915
2418
  try {
2916
2419
  realDestination = fs_1.default.realpathSync(destinationPath);
@@ -2918,34 +2421,13 @@ class AgentVariantsOrchestrator {
2918
2421
  catch {
2919
2422
  realDestination = undefined;
2920
2423
  }
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
2424
  const commitPolicy = (0, runPlan_1.resolveRunPlanPolicy)(projectContext).commit;
2926
2425
  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
2426
  if (isViteApp) {
2935
2427
  this.assertDestinationAvailable(destinationPath);
2936
2428
  }
2937
2429
  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
2430
  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
2431
  const anyAssetBaseIsDestination = [
2950
2432
  ...resources.staticPreviews.values(),
2951
2433
  ].some((sp) => sp.assetBase === compareBase);
@@ -2960,16 +2442,6 @@ class AgentVariantsOrchestrator {
2960
2442
  }
2961
2443
  }
2962
2444
  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
2445
  const record = resources.worktrees.get(args.variantId);
2974
2446
  if (!record) {
2975
2447
  throw new errors_1.AgentVariantsError('WORK_ITEM_NOT_FOUND', `Unknown variantId ${args.variantId} for session ${args.sessionId}`);
@@ -2978,18 +2450,6 @@ class AgentVariantsOrchestrator {
2978
2450
  let isDependencyInstallRequired = false;
2979
2451
  try {
2980
2452
  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
2453
  await this.stopAllDevServersForSession(resources);
2994
2454
  isDependencyInstallRequired = await resolveNodeModulesSymlink(record.worktreePath);
2995
2455
  await this.renameWorktreeIntoDestination(record.worktreePath, destinationPath);
@@ -3005,21 +2465,6 @@ class AgentVariantsOrchestrator {
3005
2465
  }
3006
2466
  changedFilesCount = countWorktreeFiles(destinationPath);
3007
2467
  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
2468
  void this.installDependencies(destinationPath)
3024
2469
  .then(() => this.startCommittedDevServer({
3025
2470
  resources,
@@ -3033,9 +2478,6 @@ class AgentVariantsOrchestrator {
3033
2478
  await this.installDependencies(destinationPath);
3034
2479
  }
3035
2480
  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
2481
  try {
3040
2482
  runnablePaths = this.preserveUnchosenVariants({
3041
2483
  sessionId: args.sessionId,
@@ -3046,12 +2488,6 @@ class AgentVariantsOrchestrator {
3046
2488
  catch (err) {
3047
2489
  log.warn(`preserveUnchosenVariants failed for session ${args.sessionId}; continuing without history`, err);
3048
2490
  }
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
2491
  committedPreviewPort = await this.startCommittedDevServer({
3056
2492
  resources,
3057
2493
  destinationPath,
@@ -3069,18 +2505,7 @@ class AgentVariantsOrchestrator {
3069
2505
  envelopeDestination = destinationPath;
3070
2506
  }
3071
2507
  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
2508
  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
2509
  const htmlFromDir = staticPreview
3085
2510
  ? this.getStaticPreviewHtml(args.sessionId, args.variantId)
3086
2511
  : undefined;
@@ -3094,21 +2519,6 @@ class AgentVariantsOrchestrator {
3094
2519
  }
3095
2520
  try {
3096
2521
  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
2522
  let flattenBase = realDestination;
3113
2523
  if (!flattenBase) {
3114
2524
  try {
@@ -3119,32 +2529,17 @@ class AgentVariantsOrchestrator {
3119
2529
  }
3120
2530
  }
3121
2531
  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
2532
  if (chosenAssetBase &&
3126
2533
  isStrictlyInside(chosenAssetBase, flattenBase)) {
3127
2534
  for (const entry of fs_1.default.readdirSync(chosenAssetBase)) {
3128
2535
  const src = path_1.default.join(chosenAssetBase, entry);
3129
2536
  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
2537
  if (path_1.default.resolve(dst) === path_1.default.resolve(chosenAssetBase)) {
3139
2538
  continue;
3140
2539
  }
3141
2540
  if (fs_1.default.existsSync(dst)) {
3142
2541
  fs_1.default.rmSync(dst, { recursive: true, force: true });
3143
2542
  }
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
2543
  try {
3149
2544
  fs_1.default.renameSync(src, dst);
3150
2545
  }
@@ -3173,10 +2568,6 @@ class AgentVariantsOrchestrator {
3173
2568
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `Failed to write static preview to ${destinationPath}: ${message}`);
3174
2569
  }
3175
2570
  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
2571
  committedPreviewPort = await this.startCommittedDevServer({
3181
2572
  resources,
3182
2573
  destinationPath,
@@ -3192,10 +2583,6 @@ class AgentVariantsOrchestrator {
3192
2583
  }
3193
2584
  }
3194
2585
  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
2586
  const env = await this.resolveEnv(args.sessionId);
3200
2587
  const record = resources.worktrees.get(args.variantId);
3201
2588
  if (!record) {
@@ -3205,8 +2592,6 @@ class AgentVariantsOrchestrator {
3205
2592
  throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Variant ${args.variantId} has no captured diff yet — wait for report_variant_complete(succeeded) first`);
3206
2593
  }
3207
2594
  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
2595
  if (!this.worktrees.applyDiffToProject) {
3211
2596
  throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'WorktreeManager does not support applying diffs to the project tree');
3212
2597
  }
@@ -3234,17 +2619,10 @@ class AgentVariantsOrchestrator {
3234
2619
  changedFilesCount,
3235
2620
  payload,
3236
2621
  };
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
2622
  this.store.recordVariantPick({
3241
2623
  sessionId: args.sessionId,
3242
2624
  envelope,
3243
2625
  });
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
2626
  const historyProjectPath = projectContext.kind === 'fresh'
3249
2627
  ? projectContext.workspacePath
3250
2628
  : envelopeDestination;
@@ -3262,13 +2640,6 @@ class AgentVariantsOrchestrator {
3262
2640
  log.warn(`persistVariantHistoryAtCommit failed for session ${args.sessionId}`, err);
3263
2641
  }
3264
2642
  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
2643
  if (this.activeSessionId === args.sessionId &&
3273
2644
  payload.kind !== 'project-created') {
3274
2645
  this.activeSessionId = null;
@@ -3288,9 +2659,6 @@ class AgentVariantsOrchestrator {
3288
2659
  this.emitChange();
3289
2660
  log.info(`Variant ${args.variantId} (${input.briefLabel}) committed by user`);
3290
2661
  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
2662
  void this.teardownSession(args.sessionId, 'committed').catch((err) => {
3295
2663
  log.warn(`teardownSession after commit failed for ${args.sessionId}`, err);
3296
2664
  });
@@ -3311,25 +2679,7 @@ class AgentVariantsOrchestrator {
3311
2679
  async cleanupCommittedSession(sessionId) {
3312
2680
  await this.teardownSession(sessionId, 'committed');
3313
2681
  }
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()) {
2682
+ assertDestinationAvailable(destinationPath, additionalAllowedEntries = new Set()) {
3333
2683
  if (!fs_1.default.existsSync(destinationPath))
3334
2684
  return;
3335
2685
  const entries = fs_1.default.readdirSync(destinationPath);
@@ -3340,18 +2690,13 @@ class AgentVariantsOrchestrator {
3340
2690
  return;
3341
2691
  throw new errors_1.AgentVariantsError('DESTINATION_NOT_EMPTY', `Destination ${destinationPath} is not empty (${userVisibleEntries.length} entries) — refuse to materialize.`);
3342
2692
  }
3343
- /** Read the captured diff for a code-gen variant, if available. */
3344
2693
  getVariantDiff(sessionId, variantId) {
3345
2694
  return this.resources.get(sessionId)?.worktrees.get(variantId)?.diff;
3346
2695
  }
3347
- // --- Side-effect implementations ----------------------------------------
3348
2696
  async provisionWorktrees(sessionId, approveResult) {
3349
2697
  const projectContext = this.store.getProjectContext(sessionId);
3350
2698
  const variantCount = approveResult.codeGenWorkItemIds.length +
3351
2699
  (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
2700
  if ((0, runPlan_1.resolveRunPlanPolicy)(projectContext).provision === 'none') {
3356
2701
  return;
3357
2702
  }
@@ -3364,10 +2709,6 @@ class AgentVariantsOrchestrator {
3364
2709
  });
3365
2710
  const run = async () => {
3366
2711
  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
2712
  await this.provisionFreshWorktrees(sessionId, approveResult, projectContext);
3372
2713
  return;
3373
2714
  }
@@ -3398,9 +2739,6 @@ class AgentVariantsOrchestrator {
3398
2739
  ? err.code
3399
2740
  : 'PROVISION_FAILED',
3400
2741
  });
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
2742
  void this.cancel({ sessionId, reason: 'provisioning_failed' }).catch((teardownErr) => {
3405
2743
  log.warn(`cleanup after provisioning failure for ${sessionId} failed`, teardownErr);
3406
2744
  });
@@ -3415,10 +2753,6 @@ class AgentVariantsOrchestrator {
3415
2753
  throw err;
3416
2754
  }
3417
2755
  }
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
2756
  async provisionExistingWorktrees(sessionId, approveResult) {
3423
2757
  const resources = this.ensureResources(sessionId);
3424
2758
  const totalCount = approveResult.codeGenWorkItemIds.length +
@@ -3445,19 +2779,6 @@ class AgentVariantsOrchestrator {
3445
2779
  });
3446
2780
  }
3447
2781
  }
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
2782
  async provisionFreshWorktrees(sessionId, approveResult, projectContext) {
3462
2783
  const resources = this.ensureResources(sessionId);
3463
2784
  const scaffoldId = approveResult.scaffoldBaseWorkItemId;
@@ -3484,33 +2805,14 @@ class AgentVariantsOrchestrator {
3484
2805
  designContext: summarizeDesignContext(designContext),
3485
2806
  });
3486
2807
  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
2808
  const destinationParent = projectContext.workspaceRoot;
3497
2809
  const paths = await createFresh.call(this.worktrees, sessionId, codeGenIds.length, viteReactTs_1.VITE_REACT_TS_TEMPLATE, designContext, destinationParent);
3498
2810
  resources.scaffoldBaseWorkItemId = scaffoldId;
3499
2811
  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
2812
  await Promise.all(codeGenIds.map((workItemId, index) => this.registerWorktreeWorkspace(resources, {
3503
2813
  workItemId,
3504
2814
  worktreePath: paths[index],
3505
2815
  })));
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
2816
  const assetPlan = projectContext.executionPlan?.assetPlan ?? [];
3515
2817
  if (assetPlan.length > 0) {
3516
2818
  try {
@@ -3542,18 +2844,10 @@ class AgentVariantsOrchestrator {
3542
2844
  return;
3543
2845
  }
3544
2846
  }
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
2847
  void this.runBackgroundInstall(sessionId, scaffoldId, paths, scaffoldStartedAt).catch((err) => {
3549
2848
  log.error(`runBackgroundInstall failed for session ${sessionId}`, err);
3550
2849
  });
3551
2850
  }
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
2851
  async runBackgroundInstall(sessionId, scaffoldWorkItemId, worktreePaths, scaffoldStartedAt) {
3558
2852
  const installStartedAt = Date.now();
3559
2853
  try {
@@ -3563,8 +2857,6 @@ class AgentVariantsOrchestrator {
3563
2857
  })));
3564
2858
  }
3565
2859
  catch (err) {
3566
- // Teardown aborts in-flight preparation; a cancelled session is not a
3567
- // scaffold failure.
3568
2860
  const resources = this.resources.get(sessionId);
3569
2861
  if (!resources || resources.cleanupStarted)
3570
2862
  return;
@@ -3606,12 +2898,6 @@ class AgentVariantsOrchestrator {
3606
2898
  variantCount: worktreePaths.length,
3607
2899
  });
3608
2900
  }
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
2901
  async evaluateQaForReport(args) {
3616
2902
  if (args.status !== 'succeeded')
3617
2903
  return null;
@@ -3619,15 +2905,12 @@ class AgentVariantsOrchestrator {
3619
2905
  return null;
3620
2906
  const projectContext = this.store.getProjectContext(args.sessionId);
3621
2907
  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
2908
  if (projectContext.kind !== 'fresh') {
3625
2909
  if (kind === 'code_gen') {
3626
2910
  return this.evaluateExistingCodeGenQa(args);
3627
2911
  }
3628
2912
  return null;
3629
2913
  }
3630
- // Resolve the objective base QA for this deliverable kind.
3631
2914
  let baseQa = null;
3632
2915
  const checkedSource = undefined;
3633
2916
  if (kind === 'static_preview') {
@@ -3637,8 +2920,6 @@ class AgentVariantsOrchestrator {
3637
2920
  baseQa = await this.runPreviewQaSafely(args, parsed.html);
3638
2921
  }
3639
2922
  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
2923
  return null;
3643
2924
  }
3644
2925
  else {
@@ -3656,7 +2937,6 @@ class AgentVariantsOrchestrator {
3656
2937
  },
3657
2938
  };
3658
2939
  }
3659
- // Synthesize a passing base verdict for vite_app (no objective layer).
3660
2940
  const passedBase = baseQa ?? {
3661
2941
  status: 'passed',
3662
2942
  issues: [],
@@ -3740,8 +3020,6 @@ class AgentVariantsOrchestrator {
3740
3020
  },
3741
3021
  };
3742
3022
  }
3743
- /** Run the injected preview QA runner, converting a thrown runner into a
3744
- * failed `VariantQaResult` (mirrors the prior inline behavior). */
3745
3023
  async runPreviewQaSafely(args, html) {
3746
3024
  try {
3747
3025
  return await this.previewQaRunner({
@@ -3768,11 +3046,6 @@ class AgentVariantsOrchestrator {
3768
3046
  memoizeQa(sessionId, workItemId, qa) {
3769
3047
  this.ensureResources(sessionId).qaResults.set(workItemId, qa);
3770
3048
  }
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
3049
  async handleQaRegenRetry(args, qa) {
3777
3050
  const resources = this.ensureResources(args.sessionId);
3778
3051
  const result = this.store.requeueForRegeneration({
@@ -3794,11 +3067,6 @@ class AgentVariantsOrchestrator {
3794
3067
  overall: null,
3795
3068
  });
3796
3069
  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
3070
  const completionResult = { ...result, requeuedForRegeneration: true, qa };
3803
3071
  resources.repairCompletionResults.set(repairCompletionKey(args), completionResult);
3804
3072
  return completionResult;
@@ -3817,16 +3085,6 @@ class AgentVariantsOrchestrator {
3817
3085
  args.record.pendingAutoRestart !== args.autoRestartTimer;
3818
3086
  return Boolean(resources && !resources.cleanupStarted && !isAutoRestartCancelled);
3819
3087
  };
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
3088
  const previewStartedAt = Date.now();
3831
3089
  const projectContextKind = args.isFresh ? 'fresh' : 'existing';
3832
3090
  trackPreviewStarted(this.telemetry, {
@@ -3838,13 +3096,9 @@ class AgentVariantsOrchestrator {
3838
3096
  const startPort = await this.resolveDevServerStartPort(args.sessionId, args.isFresh);
3839
3097
  let scanFrom = startPort;
3840
3098
  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
3099
  let installRetried = false;
3844
3100
  let lastDev;
3845
3101
  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
3102
  if (!canContinueStart())
3849
3103
  return undefined;
3850
3104
  let port;
@@ -3855,10 +3109,6 @@ class AgentVariantsOrchestrator {
3855
3109
  if (!canContinueStart())
3856
3110
  return undefined;
3857
3111
  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
3112
  if (!canContinueStart()) {
3863
3113
  log.info(`Variant ${args.workItemId} dev server booted after preview cleanup; stopping it`);
3864
3114
  void this.worktrees.stopDevServer(proc).catch(() => undefined);
@@ -3870,16 +3120,6 @@ class AgentVariantsOrchestrator {
3870
3120
  args.record.port = port;
3871
3121
  args.record.devServerProcess = proc;
3872
3122
  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
3123
  proc.once('exit', (code, signal) => {
3884
3124
  if (args.record.devServerProcess !== proc)
3885
3125
  return;
@@ -3898,8 +3138,6 @@ class AgentVariantsOrchestrator {
3898
3138
  args.record.devServerAutoRestarts = restartsUsed + 1;
3899
3139
  this.emitChange();
3900
3140
  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
3141
  const current = this.resources.get(args.sessionId);
3904
3142
  if (!current ||
3905
3143
  current.cleanupStarted ||
@@ -3927,8 +3165,6 @@ class AgentVariantsOrchestrator {
3927
3165
  });
3928
3166
  this.emitChange();
3929
3167
  });
3930
- // A prior failure record (startup failure before a successful retry,
3931
- // idle reclaim, crash before this restart) is now stale.
3932
3168
  this.resources
3933
3169
  .get(args.sessionId)
3934
3170
  ?.previewFailures.delete(args.workItemId);
@@ -3957,16 +3193,6 @@ class AgentVariantsOrchestrator {
3957
3193
  const devErr = (0, devServerError_1.isDevServerStartError)(err) ? err : undefined;
3958
3194
  const portInUse = devErr?.portInUse ?? false;
3959
3195
  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
3196
  const missingDepsOutput = (0, devServerError_1.isMissingDependencyOutput)(devErr?.detail ?? '');
3971
3197
  const missingDeps = missingDepsOutput &&
3972
3198
  reason === 'exited' &&
@@ -3975,8 +3201,6 @@ class AgentVariantsOrchestrator {
3975
3201
  canInstallWithoutTouchingHost(lastDev.cwd);
3976
3202
  const willRetry = attempt < maxAttempts &&
3977
3203
  (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
3204
  scanFrom = (port ?? scanFrom) + 1;
3981
3205
  log.warn(`Failed to start dev server for variant ${args.workItemId} on port ${port ?? 'unallocated'} ` +
3982
3206
  `(attempt ${attempt}/${maxAttempts}, reason=${reason}, portInUse=${portInUse}, missingDeps=${missingDeps})` +
@@ -4020,9 +3244,6 @@ class AgentVariantsOrchestrator {
4020
3244
  }
4021
3245
  continue;
4022
3246
  }
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
3247
  this.resources
4027
3248
  .get(args.sessionId)
4028
3249
  ?.previewFailures.set(args.workItemId, {
@@ -4034,10 +3255,6 @@ class AgentVariantsOrchestrator {
4034
3255
  errorCode = 'DEPENDENCY_INSTALL_FAILED';
4035
3256
  if (reason === 'missing_dev_script')
4036
3257
  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
3258
  trackFreshDevServerFailed(this.telemetry, {
4042
3259
  sessionId: args.sessionId,
4043
3260
  variantId: args.workItemId,
@@ -4065,9 +3282,6 @@ class AgentVariantsOrchestrator {
4065
3282
  return undefined;
4066
3283
  }
4067
3284
  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
3285
  if (port !== undefined)
4072
3286
  this.worktrees.releasePort?.(port);
4073
3287
  }
@@ -4095,12 +3309,6 @@ class AgentVariantsOrchestrator {
4095
3309
  assetBase: staticPreview.assetBase,
4096
3310
  projectContext,
4097
3311
  });
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
3312
  const workspacePath = projectContext.kind === 'fresh'
4105
3313
  ? projectContext.workspacePath
4106
3314
  : undefined;
@@ -4123,17 +3331,10 @@ class AgentVariantsOrchestrator {
4123
3331
  }
4124
3332
  try {
4125
3333
  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
3334
  try {
4132
3335
  dir = fs_1.default.realpathSync(dir);
4133
3336
  }
4134
- catch {
4135
- // keep the un-realpath'd path if realpath fails
4136
- }
3337
+ catch { }
4137
3338
  fs_1.default.writeFileSync(path_1.default.join(dir, 'index.html'), staticPreview.html, 'utf8');
4138
3339
  }
4139
3340
  catch (err) {
@@ -4153,8 +3354,6 @@ class AgentVariantsOrchestrator {
4153
3354
  resources.workspaceManager.removeArtifactWorkspace(workItemId);
4154
3355
  }
4155
3356
  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
3357
  this.trackHistoryPersist(this.persistCompletedFreshVariant({
4159
3358
  sessionId,
4160
3359
  workItemId,
@@ -4185,8 +3384,6 @@ class AgentVariantsOrchestrator {
4185
3384
  log.warn(`No worktree record for ${sessionId}/${workItemId}; skipping diff capture`);
4186
3385
  return;
4187
3386
  }
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
3387
  if (resources.scaffoldBaseWorkItemId === workItemId) {
4191
3388
  log.info(`scaffold_base ${workItemId} succeeded; awaiting dependent code-gen`);
4192
3389
  return;
@@ -4202,14 +3399,6 @@ class AgentVariantsOrchestrator {
4202
3399
  catch (err) {
4203
3400
  log.warn(`getDiff failed for ${record.worktreePath}`, err);
4204
3401
  }
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
3402
  if (!isFresh) {
4214
3403
  this.trackHistoryPersist(this.persistCompletedExistingVariant({
4215
3404
  sessionId,
@@ -4227,19 +3416,8 @@ class AgentVariantsOrchestrator {
4227
3416
  log.warn(`persistCompletedFreshVariant failed for ${sessionId}/${workItemId}`, err);
4228
3417
  }));
4229
3418
  }
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
3419
  if (!isFresh) {
4238
3420
  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
3421
  if (staticPreview !== 'not_static') {
4244
3422
  this.emitChange();
4245
3423
  return;
@@ -4273,17 +3451,8 @@ class AgentVariantsOrchestrator {
4273
3451
  assetBase: parsed.assetBase,
4274
3452
  projectContext: this.store.getProjectContext(args.sessionId),
4275
3453
  });
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
3454
  const previousRecord = resources.staticPreviews.get(input.variantId);
4281
3455
  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
3456
  if (dir) {
4288
3457
  try {
4289
3458
  fs_1.default.mkdirSync(dir, { recursive: true });
@@ -4293,9 +3462,6 @@ class AgentVariantsOrchestrator {
4293
3462
  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
3463
  }
4295
3464
  }
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
3465
  this.store.replaceWorkItemOutput(args.sessionId, input.variantId, {
4300
3466
  ...parsed,
4301
3467
  ...(dir ? { assetBase: dir } : {}),
@@ -4317,10 +3483,6 @@ class AgentVariantsOrchestrator {
4317
3483
  targetWorkItemId: input.variantId,
4318
3484
  });
4319
3485
  }
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
3486
  try {
4325
3487
  await this.persistCompletedFreshVariant({
4326
3488
  sessionId: args.sessionId,
@@ -4330,22 +3492,10 @@ class AgentVariantsOrchestrator {
4330
3492
  catch (err) {
4331
3493
  log.warn(`persistCompletedFreshVariant failed for refined variant ${input.variantId} (session ${args.sessionId}); preview already swapped`, err);
4332
3494
  }
4333
- // The caller (reportComplete) emits the change after recording success so
4334
- // the snapshot reflects both the swapped HTML and refinement.status.
4335
3495
  }
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
3496
  get devServerManager() {
4342
3497
  return this.worktrees;
4343
3498
  }
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
3499
  pendingHistoryPersists = new Set();
4350
3500
  trackHistoryPersist(persist) {
4351
3501
  this.pendingHistoryPersists.add(persist);
@@ -4355,20 +3505,11 @@ class AgentVariantsOrchestrator {
4355
3505
  this.pendingHistoryPersists.delete(persist);
4356
3506
  });
4357
3507
  }
4358
- /** Await every in-flight history persist, including ones that start while
4359
- * draining (a refine can persist mid-settle). */
4360
3508
  async settleHistoryPersists() {
4361
3509
  while (this.pendingHistoryPersists.size > 0) {
4362
3510
  await Promise.allSettled([...this.pendingHistoryPersists]);
4363
3511
  }
4364
3512
  }
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
3513
  async persistCompletedExistingVariant(args) {
4373
3514
  const projectContext = this.store.getProjectContext(args.sessionId);
4374
3515
  if (projectContext.kind !== 'existing')
@@ -4396,13 +3537,7 @@ class AgentVariantsOrchestrator {
4396
3537
  }
4397
3538
  const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
4398
3539
  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
3540
  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
3541
  let baseDir;
4407
3542
  try {
4408
3543
  baseDir = await this.worktrees.getGitRoot?.();
@@ -4412,9 +3547,6 @@ class AgentVariantsOrchestrator {
4412
3547
  }
4413
3548
  let serve;
4414
3549
  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
3550
  const entryPath = path_1.default.relative(record.worktreePath, path_1.default.join(sourceDir, staticEntryPath));
4419
3551
  serve = { kind: 'static', entryPath };
4420
3552
  }
@@ -4425,12 +3557,6 @@ class AgentVariantsOrchestrator {
4425
3557
  };
4426
3558
  }
4427
3559
  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
3560
  try {
4435
3561
  const dev = await this.resolveDevServerCommand(args.sessionId, record.worktreePath, RECIPE_PORT_SENTINEL, false);
4436
3562
  serve = {
@@ -4449,6 +3575,12 @@ class AgentVariantsOrchestrator {
4449
3575
  ...(input.requestId ? { requestId: input.requestId } : {}),
4450
3576
  label: input.briefLabel,
4451
3577
  brief: input.briefBody,
3578
+ references: input.references,
3579
+ referenceContext: input.context,
3580
+ referenceContextRoots: [
3581
+ path_1.default.join(this.variantHistory.store.storage.resolve(env.projectPath)
3582
+ .dataDirectory, 'variant-context'),
3583
+ ],
4452
3584
  sessionPrompt,
4453
3585
  runLabel: input.runLabel ?? this.store.getRunLabel(args.sessionId),
4454
3586
  kind: 'diff',
@@ -4470,22 +3602,6 @@ class AgentVariantsOrchestrator {
4470
3602
  : {}),
4471
3603
  });
4472
3604
  }
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
3605
  async registerExistingStaticPreview(sessionId, workItemId, record) {
4490
3606
  let env;
4491
3607
  try {
@@ -4518,9 +3634,6 @@ class AgentVariantsOrchestrator {
4518
3634
  log.warn(`registerExistingStaticPreview: project cwd failed for ${sessionId}/${workItemId}`, err);
4519
3635
  return 'unavailable';
4520
3636
  }
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
3637
  const entryFile = path_1.default.join(projectCwd, env.entryPath);
4525
3638
  try {
4526
3639
  await fs_1.default.promises.access(entryFile, fs_1.default.constants.R_OK);
@@ -4542,41 +3655,25 @@ class AgentVariantsOrchestrator {
4542
3655
  });
4543
3656
  return 'unavailable';
4544
3657
  }
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
3658
  let dir;
4549
3659
  try {
4550
3660
  dir = fs_1.default.realpathSync(projectCwd);
4551
3661
  }
4552
3662
  catch {
4553
- // Fall back to the un-realpath'd cwd; serving still works, only the
4554
- // sandbox symlink-normalization is skipped.
4555
3663
  dir = projectCwd;
4556
3664
  }
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
3665
  let assetFallbackBase;
4563
3666
  try {
4564
3667
  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
3668
  if (hostRealRoot !== dir)
4568
3669
  assetFallbackBase = hostRealRoot;
4569
3670
  }
4570
- catch {
4571
- // No host root resolvable — serve worktree assets only.
4572
- }
3671
+ catch { }
4573
3672
  resources.staticPreviews.set(workItemId, {
4574
3673
  workItemId,
4575
3674
  briefId: input.briefId,
4576
3675
  entryPath: env.entryPath,
4577
3676
  assetBase: dir,
4578
- // Existing-mode static projects are real multi-file sites — assume
4579
- // sibling assets so the preview route resolves relative URLs.
4580
3677
  hasAssets: true,
4581
3678
  ...(assetFallbackBase ? { assetFallbackBase } : {}),
4582
3679
  });
@@ -4592,25 +3689,10 @@ class AgentVariantsOrchestrator {
4592
3689
  });
4593
3690
  return 'registered';
4594
3691
  }
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
3692
  async persistCompletedFreshVariant(args) {
4609
3693
  const projectContext = this.store.getProjectContext(args.sessionId);
4610
3694
  if (projectContext.kind !== 'fresh')
4611
3695
  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
3696
  const historyProjectPath = projectContext.workspacePath;
4615
3697
  const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
4616
3698
  const sessionPrompt = this.store.getPrompt(args.sessionId);
@@ -4618,11 +3700,6 @@ class AgentVariantsOrchestrator {
4618
3700
  const resources = this.resources.get(args.sessionId);
4619
3701
  const worktreeRecord = resources?.worktrees.get(args.workItemId);
4620
3702
  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
3703
  let sourceDir = null;
4627
3704
  let tmpStagingDir = null;
4628
3705
  if (worktreeRecord && fs_1.default.existsSync(worktreeRecord.worktreePath)) {
@@ -4631,7 +3708,6 @@ class AgentVariantsOrchestrator {
4631
3708
  else if (staticPreview) {
4632
3709
  tmpStagingDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `rivet-variant-${args.workItemId}-`));
4633
3710
  copyStaticPreviewDirectory(staticPreview.assetBase, tmpStagingDir);
4634
- // Read the materialized index.html from the variant's per-variant dir.
4635
3711
  let stagedHtml = '';
4636
3712
  try {
4637
3713
  stagedHtml = fs_1.default.readFileSync(path_1.default.join(staticPreview.assetBase, 'index.html'), 'utf8');
@@ -4647,10 +3723,6 @@ class AgentVariantsOrchestrator {
4647
3723
  log.warn(`persistCompletedFreshVariant: no source for ${args.workItemId} (session ${args.sessionId}); skipping`);
4648
3724
  return;
4649
3725
  }
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
3726
  const changedFilesCount = staticPreview ? 1 : countWorktreeFiles(sourceDir);
4655
3727
  const preview = staticPreview
4656
3728
  ? { kind: 'static', entryPath: 'index.html' }
@@ -4662,12 +3734,6 @@ class AgentVariantsOrchestrator {
4662
3734
  script: 'dev',
4663
3735
  },
4664
3736
  };
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
3737
  const serve = staticPreview
4672
3738
  ? { kind: 'static', entryPath: 'index.html' }
4673
3739
  : worktreeRecord?.devCommand && worktreeRecord.port !== undefined
@@ -4700,6 +3766,15 @@ class AgentVariantsOrchestrator {
4700
3766
  ...(input.requestId ? { requestId: input.requestId } : {}),
4701
3767
  label: input.briefLabel,
4702
3768
  brief: input.briefBody,
3769
+ references: input.references,
3770
+ referenceContext: input.context,
3771
+ referenceContextRoots: [
3772
+ projectContext.workspacePath,
3773
+ projectContext.workspaceRoot,
3774
+ ]
3775
+ .filter((projectPath) => Boolean(projectPath))
3776
+ .map((projectPath) => path_1.default.join(this.variantHistory.store.storage.resolve(projectPath)
3777
+ .dataDirectory, 'variant-context')),
4703
3778
  sessionPrompt,
4704
3779
  runLabel: input.runLabel ?? this.store.getRunLabel(args.sessionId),
4705
3780
  kind: 'project-created',
@@ -4730,10 +3805,6 @@ class AgentVariantsOrchestrator {
4730
3805
  }
4731
3806
  }
4732
3807
  }
4733
- /**
4734
- * @effect Drains fresh-project history writes before commit moves or rewrites
4735
- * the generated project folder.
4736
- */
4737
3808
  async persistCompletedFreshVariantsForCommit(sessionId) {
4738
3809
  const projectContext = this.store.getProjectContext(sessionId);
4739
3810
  if (projectContext.kind !== 'fresh')
@@ -4753,14 +3824,6 @@ class AgentVariantsOrchestrator {
4753
3824
  }
4754
3825
  }
4755
3826
  }
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
3827
  async persistVariantHistoryAtCommit(args) {
4765
3828
  const variants = this.store.getVariants(args.sessionId);
4766
3829
  for (const variant of variants) {
@@ -4781,13 +3844,6 @@ class AgentVariantsOrchestrator {
4781
3844
  });
4782
3845
  }
4783
3846
  }
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
3847
  async markPersistedVariantsCancelled(sessionId) {
4792
3848
  if (!this.store.hasSession(sessionId))
4793
3849
  return;
@@ -4823,9 +3879,6 @@ class AgentVariantsOrchestrator {
4823
3879
  const projectPath = await this.resolveHistoryProjectPath(sessionId);
4824
3880
  if (!projectPath)
4825
3881
  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
3882
  await this.variantHistory.markStatus({
4830
3883
  projectPath,
4831
3884
  sessionId,
@@ -4839,9 +3892,6 @@ class AgentVariantsOrchestrator {
4839
3892
  const projectPath = await this.resolveHistoryProjectPath(sessionId);
4840
3893
  if (!projectPath)
4841
3894
  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
3895
  await this.variantHistory.renameVariant({
4846
3896
  projectPath,
4847
3897
  sessionId,
@@ -4850,11 +3900,6 @@ class AgentVariantsOrchestrator {
4850
3900
  runLabel,
4851
3901
  });
4852
3902
  }
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
3903
  async resolveHistoryProjectPath(sessionId) {
4859
3904
  const projectContext = this.store.getProjectContext(sessionId);
4860
3905
  if (projectContext.kind === 'fresh') {
@@ -4881,13 +3926,6 @@ class AgentVariantsOrchestrator {
4881
3926
  return undefined;
4882
3927
  }
4883
3928
  }
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
3929
  async resolveDevServerStartPort(sessionId, isFresh) {
4892
3930
  if (isFresh)
4893
3931
  return FRESH_DEV_SERVER_DEFAULT_PORT;
@@ -4899,11 +3937,6 @@ class AgentVariantsOrchestrator {
4899
3937
  return 3000;
4900
3938
  }
4901
3939
  }
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
3940
  async resolveDevServer(sessionId, worktreePath, port, isFresh) {
4908
3941
  const resolved = await this.resolveDevServerCommand(sessionId, worktreePath, port, isFresh);
4909
3942
  await this.ensureProjectDependencies({
@@ -4913,13 +3946,6 @@ class AgentVariantsOrchestrator {
4913
3946
  });
4914
3947
  return resolved;
4915
3948
  }
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
3949
  async resolveDevServerCommand(sessionId, worktreePath, port, isFresh) {
4924
3950
  if (isFresh) {
4925
3951
  return {
@@ -4943,9 +3969,6 @@ class AgentVariantsOrchestrator {
4943
3969
  throw new Error('Static projects do not have a dev server command');
4944
3970
  }
4945
3971
  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
3972
  if (env.devCommand) {
4950
3973
  assertDevScriptExists(cwd, env.devCommand);
4951
3974
  }
@@ -4981,7 +4004,6 @@ class AgentVariantsOrchestrator {
4981
4004
  packageManager,
4982
4005
  };
4983
4006
  }
4984
- /** Prepares the direction's declared dependencies before each server start. */
4985
4007
  async ensureProjectDependencies(args) {
4986
4008
  if (!fs_1.default.existsSync(path_1.default.join(args.cwd, 'package.json')))
4987
4009
  return;
@@ -4990,13 +4012,6 @@ class AgentVariantsOrchestrator {
4990
4012
  signal: args.signal,
4991
4013
  });
4992
4014
  }
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
4015
  async resolveExistingProjectCwd(sessionId, worktreePath, env) {
5001
4016
  const fallback = await this.worktrees.getProjectCwdInWorktree(worktreePath);
5002
4017
  try {
@@ -5014,16 +4029,6 @@ class AgentVariantsOrchestrator {
5014
4029
  return fallback;
5015
4030
  }
5016
4031
  }
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
4032
  preserveUnchosenVariants(args) {
5028
4033
  const resources = this.resources.get(args.sessionId);
5029
4034
  const runnablePaths = new Map();
@@ -5059,8 +4064,6 @@ class AgentVariantsOrchestrator {
5059
4064
  }
5060
4065
  const record = resources.worktrees.get(variant.workItemId);
5061
4066
  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
4067
  manifestEntries.push({
5065
4068
  variantId: variant.workItemId,
5066
4069
  label,
@@ -5089,8 +4092,6 @@ class AgentVariantsOrchestrator {
5089
4092
  fs_1.default.renameSync(record.worktreePath, dest);
5090
4093
  return dest;
5091
4094
  })();
5092
- // Update the in-memory record so teardown doesn't try to operate on
5093
- // the stale path.
5094
4095
  record.worktreePath = newPath;
5095
4096
  runnablePaths.set(variant.workItemId, `${path_1.default.basename(historyDir)}/${folderName}`);
5096
4097
  manifestEntries.push({
@@ -5129,22 +4130,7 @@ class AgentVariantsOrchestrator {
5129
4130
  resources.vitePreservedSiblings = true;
5130
4131
  return runnablePaths;
5131
4132
  }
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
4133
  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
4134
  const destinationParent = path_1.default.dirname(destinationPath);
5149
4135
  await fs_1.default.promises.mkdir(destinationParent, { recursive: true });
5150
4136
  let preservedRivetParent;
@@ -5191,16 +4177,11 @@ class AgentVariantsOrchestrator {
5191
4177
  force: true,
5192
4178
  });
5193
4179
  }
5194
- // Replace the variant-baseline git history with a fresh init so the
5195
- // user doesn't inherit a `rivet: variant baseline` commit.
5196
4180
  const dotGit = path_1.default.join(destinationPath, '.git');
5197
4181
  try {
5198
4182
  fs_1.default.rmSync(dotGit, { recursive: true, force: true });
5199
4183
  }
5200
- catch {
5201
- // Best-effort — leaving the baseline .git is preferable to failing
5202
- // the commit after we've moved the tree.
5203
- }
4184
+ catch { }
5204
4185
  try {
5205
4186
  const git = (0, simple_git_1.simpleGit)(destinationPath);
5206
4187
  await git.raw(['init']);
@@ -5216,23 +4197,12 @@ class AgentVariantsOrchestrator {
5216
4197
  '-m',
5217
4198
  'Initial commit (created with Rivet)',
5218
4199
  ])
5219
- .catch(() => {
5220
- // Best-effort: missing user identity or empty tree leaves the
5221
- // commit step un-applied. Files are still in place.
5222
- });
4200
+ .catch(() => { });
5223
4201
  }
5224
4202
  catch (err) {
5225
4203
  log.warn(`Initial git history setup at ${destinationPath} failed`, err);
5226
4204
  }
5227
4205
  }
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
4206
  async stopAllDevServersForSession(resources) {
5237
4207
  this.clearActivePreviewIdleTimer(resources);
5238
4208
  const stops = [];
@@ -5271,7 +4241,6 @@ class AgentVariantsOrchestrator {
5271
4241
  clearTimeout(resources.activePreviewIdleTimer);
5272
4242
  resources.activePreviewIdleTimer = undefined;
5273
4243
  }
5274
- /** @effect Stops idle variant child processes and clears dead preview ports. */
5275
4244
  async stopIdleVariantDevServers(sessionId) {
5276
4245
  const resources = this.resources.get(sessionId);
5277
4246
  if (!resources || resources.cleanupStarted)
@@ -5300,8 +4269,6 @@ class AgentVariantsOrchestrator {
5300
4269
  }
5301
4270
  log.info(`Reclaimed ${expiringWorkItemIds.length} idle variant preview(s) for session ${sessionId} ` +
5302
4271
  `(${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
4272
  try {
5306
4273
  this.switchPreviewPort?.(null);
5307
4274
  }
@@ -5317,18 +4284,6 @@ class AgentVariantsOrchestrator {
5317
4284
  resources.activePreviewIdleStop = stop;
5318
4285
  await stop;
5319
4286
  }
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
4287
  async startCommittedDevServer(args) {
5333
4288
  const mode = args.mode ?? 'vite_app';
5334
4289
  try {
@@ -5353,14 +4308,6 @@ class AgentVariantsOrchestrator {
5353
4308
  port,
5354
4309
  path: args.destinationPath,
5355
4310
  };
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
4311
  try {
5365
4312
  this.setCommittedDevServerHealth?.(port);
5366
4313
  }
@@ -5381,19 +4328,9 @@ class AgentVariantsOrchestrator {
5381
4328
  return undefined;
5382
4329
  }
5383
4330
  }
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
4331
  async stopLingeringCommittedDevServers() {
5392
4332
  const entries = [...this.lingeringCommittedDevServers.entries()];
5393
4333
  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
4334
  if (entries.length > 0) {
5398
4335
  try {
5399
4336
  this.setCommittedDevServerHealth?.(null);
@@ -5422,40 +4359,20 @@ class AgentVariantsOrchestrator {
5422
4359
  log.info(`Tearing down session ${sessionId} (reason: ${reason})`);
5423
4360
  resources.dependencyAbortController.abort();
5424
4361
  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
4362
  await Promise.race([
5433
4363
  this.settleHistoryPersists(),
5434
4364
  new Promise((resolve) => setTimeout(resolve, SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS)),
5435
4365
  ]);
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
4366
  const stops = [...resources.worktrees.values()]
5442
4367
  .filter((r) => r.devServerProcess)
5443
4368
  .map((r) => this.worktrees
5444
4369
  .stopDevServer(r.devServerProcess)
5445
4370
  .catch((err) => log.warn(`stopDevServer failed for ${sessionId}/${r.workItemId}`, err)));
5446
4371
  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
4372
  if (resources.committedDevServer && reason === 'committed') {
5453
4373
  this.lingeringCommittedDevServers.set(sessionId, resources.committedDevServer);
5454
4374
  }
5455
4375
  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
4376
  try {
5460
4377
  await this.worktrees.stopDevServer(resources.committedDevServer.proc);
5461
4378
  }
@@ -5463,10 +4380,6 @@ class AgentVariantsOrchestrator {
5463
4380
  log.warn(`stopDevServer for committed dev server (session ${sessionId}) failed`, err);
5464
4381
  }
5465
4382
  }
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
4383
  if (!resources.vitePreservedSiblings) {
5471
4384
  try {
5472
4385
  await this.worktrees.cleanupSession(sessionId, resources.freshDestinationParent);
@@ -5475,10 +4388,6 @@ class AgentVariantsOrchestrator {
5475
4388
  log.warn(`cleanupSession (worktree removal) failed for ${sessionId}`, err);
5476
4389
  }
5477
4390
  }
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
4391
  const ownedArtifactRoots = new Set(resources.workspaceManager.getOwnedArtifactRoots());
5483
4392
  resources.workspaceManager.removeOwnedArtifactWorkspaces();
5484
4393
  const staticDirectories = new Set();
@@ -5536,10 +4445,6 @@ class AgentVariantsOrchestrator {
5536
4445
  }
5537
4446
  }
5538
4447
  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
4448
  function estimateOutputBytes(output) {
5544
4449
  if (output === undefined || output === null)
5545
4450
  return 0;
@@ -5563,28 +4468,11 @@ function normalizeOutput(output) {
5563
4468
  }
5564
4469
  return output;
5565
4470
  }
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
4471
  function isStrictlyInside(child, parent) {
5572
4472
  const c = path_1.default.resolve(child);
5573
4473
  const p = path_1.default.resolve(parent);
5574
4474
  return c !== p && c.startsWith(p + path_1.default.sep);
5575
4475
  }
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
4476
  function resolveAssetWithinBase(base, requestedPath) {
5589
4477
  const target = path_1.default.resolve(base, '.' + path_1.default.sep + requestedPath);
5590
4478
  if (target !== base && !target.startsWith(base + path_1.default.sep)) {
@@ -5604,11 +4492,6 @@ function resolveAssetWithinBase(base, requestedPath) {
5604
4492
  const stat = fs_1.default.statSync(realTarget);
5605
4493
  if (!stat.isFile())
5606
4494
  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
4495
  if (stat.nlink !== 1)
5613
4496
  return undefined;
5614
4497
  return realTarget;
@@ -5617,19 +4500,6 @@ function resolveAssetWithinBase(base, requestedPath) {
5617
4500
  return undefined;
5618
4501
  }
5619
4502
  }
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
4503
  function resolveStaticPreviewAssetBase(args) {
5634
4504
  if (!args.assetBase)
5635
4505
  return undefined;
@@ -5638,23 +4508,6 @@ function resolveStaticPreviewAssetBase(args) {
5638
4508
  let workspace;
5639
4509
  let resolved;
5640
4510
  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
4511
  const wsStat = fs_1.default.lstatSync(args.projectContext.workspacePath);
5659
4512
  if (wsStat.isSymbolicLink()) {
5660
4513
  log.warn(`Static preview workspacePath ${args.projectContext.workspacePath} is a symlink — refusing assetBase`);
@@ -5716,11 +4569,6 @@ function buildStaticPreviewDocument(input) {
5716
4569
  const style = input.css ? `<style>\n${input.css}\n</style>` : '';
5717
4570
  const script = input.js ? `<script>\n${input.js}\n</script>` : '';
5718
4571
  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
4572
  let doc = input.html;
5725
4573
  if (style) {
5726
4574
  if (/<\/head>/i.test(doc)) {
@@ -5754,15 +4602,8 @@ ${input.html}
5754
4602
  </html>`;
5755
4603
  }
5756
4604
  function countDiffFiles(diff) {
5757
- // Each file in a unified diff starts with "diff --git ".
5758
4605
  return (diff.match(/^diff --git /gm) ?? []).length;
5759
4606
  }
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
4607
  function countWorktreeFiles(destinationPath) {
5767
4608
  let count = 0;
5768
4609
  const walk = (dir) => {
@@ -5795,8 +4636,6 @@ const enrichDesignSource = (design) => {
5795
4636
  };
5796
4637
  };
5797
4638
  const toActiveProjectContext = (projectContext) => {
5798
- // Source count + grounding are derived purely from the read-only context
5799
- // bundle now that `sourceContext` intake is gone.
5800
4639
  const sourceCount = projectContext.variantContext?.userContext.filter((source) => source.transport !== 'prompt').length ?? 0;
5801
4640
  const hasSourceContextSummary = Boolean(sourceCount > 0 ||
5802
4641
  (projectContext.variantContext?.rivetMetadata.length ?? 0) > 0);
@@ -5839,18 +4678,6 @@ const toActiveProjectContext = (projectContext) => {
5839
4678
  : {}),
5840
4679
  };
5841
4680
  };
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
4681
  const buildSessionArtifacts = (sessionId, projectContext) => {
5855
4682
  const artifacts = buildResolvedDesignContextArtifacts(projectContext);
5856
4683
  return artifacts.map(({ content: _content, ...artifact }) => ({
@@ -6188,7 +5015,6 @@ const renderDesignMarkdown = (markdown, artifactLabel) => {
6188
5015
  const headingText = headingMatch[2].trim();
6189
5016
  const isDuplicateTitle = headingText === artifactLabel ||
6190
5017
  headingText === `${artifactLabel} DESIGN.md`;
6191
- // The viewer header already renders the artifact title.
6192
5018
  if (level === 1 && !skippedFirstH1 && isDuplicateTitle) {
6193
5019
  skippedFirstH1 = true;
6194
5020
  return;
@@ -6230,14 +5056,6 @@ const escapeHtml = (value) => {
6230
5056
  .replace(/"/g, '&quot;')
6231
5057
  .replace(/'/g, '&#39;');
6232
5058
  };
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
5059
  const resolveDesignArtifact = (entry) => {
6242
5060
  if (!entry)
6243
5061
  return null;
@@ -6462,7 +5280,6 @@ function copyStaticPreviewDirectory(src, dest) {
6462
5280
  }
6463
5281
  }
6464
5282
  }
6465
- /** Prepares an isolated project through its selected package manager. */
6466
5283
  const defaultInstallDependencies = async (worktreePath, options) => {
6467
5284
  await DependencyPreparationService_1.previewDependencies.prepare({
6468
5285
  cwd: worktreePath,
@@ -6471,14 +5288,6 @@ const defaultInstallDependencies = async (worktreePath, options) => {
6471
5288
  signal: options?.signal,
6472
5289
  });
6473
5290
  };
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
5291
  const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
6483
5292
  const portPattern = new RegExp(`(?<![0-9])${port}(?![0-9])`, 'g');
6484
5293
  const sub = (value) => value.replace(portPattern, '${PORT}');
@@ -6490,19 +5299,6 @@ const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
6490
5299
  envTemplate: Object.fromEntries(Object.entries(dev.env).map(([key, value]) => [key, sub(value)])),
6491
5300
  };
6492
5301
  };
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
5302
  const canInstallWithoutTouchingHost = (cwd) => {
6507
5303
  try {
6508
5304
  return !fs_1.default.lstatSync(path_1.default.join(cwd, 'node_modules')).isSymbolicLink();
@@ -6511,15 +5307,6 @@ const canInstallWithoutTouchingHost = (cwd) => {
6511
5307
  return true;
6512
5308
  }
6513
5309
  };
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
5310
  const assertDevScriptExists = (cwd, scriptName) => {
6524
5311
  let scripts;
6525
5312
  try {
@@ -6548,16 +5335,6 @@ const assertDevScriptExists = (cwd, scriptName) => {
6548
5335
  : '',
6549
5336
  });
6550
5337
  };
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
5338
  function areSameVolume(a, b) {
6562
5339
  try {
6563
5340
  const statA = fs_1.default.statSync(a);
@@ -6569,7 +5346,6 @@ function areSameVolume(a, b) {
6569
5346
  return false;
6570
5347
  }
6571
5348
  }
6572
- /** Clears a borrowed install so a moved generated project prepares its own dependencies. */
6573
5349
  async function resolveNodeModulesSymlink(worktreePath) {
6574
5350
  const nodeModulesPath = path_1.default.join(worktreePath, 'node_modules');
6575
5351
  try {
@@ -6610,17 +5386,8 @@ const defaultMaterializeProject = async (sourceWorktreePath, destinationPath) =>
6610
5386
  '-m',
6611
5387
  'Initial commit (created with Rivet)',
6612
5388
  ])
6613
- .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
- });
5389
+ .catch(() => { });
6617
5390
  };
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
5391
  function synthesizeUnifiedBriefBody(prompt, index, total) {
6625
5392
  const trimmed = prompt.trim().replace(/\s+/g, ' ').slice(0, 200);
6626
5393
  const intent = trimmed.length > 0 ? trimmed : 'Create this variant';