rivet-design 0.12.2 → 0.12.3

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 (70) hide show
  1. package/README.md +14 -34
  2. package/README.npm.md +14 -34
  3. package/dist/mcp/agent-variants/contracts.d.ts +561 -101
  4. package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
  5. package/dist/mcp/agent-variants/contracts.js +51 -24
  6. package/dist/mcp/agent-variants/contracts.js.map +1 -1
  7. package/dist/mcp/agent-variants/createZeroToOneTool.d.ts +1 -1
  8. package/dist/mcp/agent-variants/createZeroToOneTool.d.ts.map +1 -1
  9. package/dist/mcp/agent-variants/createZeroToOneTool.js +1 -1
  10. package/dist/mcp/agent-variants/createZeroToOneTool.js.map +1 -1
  11. package/dist/mcp/agent-variants/tools.d.ts +12 -0
  12. package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
  13. package/dist/mcp/agent-variants/tools.js +149 -247
  14. package/dist/mcp/agent-variants/tools.js.map +1 -1
  15. package/dist/mcp/auth/tools.d.ts.map +1 -1
  16. package/dist/mcp/auth/tools.js +2 -3
  17. package/dist/mcp/auth/tools.js.map +1 -1
  18. package/dist/mcp/instructions.d.ts +11 -2
  19. package/dist/mcp/instructions.d.ts.map +1 -1
  20. package/dist/mcp/instructions.js +20 -5
  21. package/dist/mcp/instructions.js.map +1 -1
  22. package/dist/mcp/integrations/tools.d.ts.map +1 -1
  23. package/dist/mcp/integrations/tools.js +33 -22
  24. package/dist/mcp/integrations/tools.js.map +1 -1
  25. package/dist/mcp/server.d.ts.map +1 -1
  26. package/dist/mcp/server.js +31 -13
  27. package/dist/mcp/server.js.map +1 -1
  28. package/dist/mcp/toolAnalytics.d.ts +11 -0
  29. package/dist/mcp/toolAnalytics.d.ts.map +1 -1
  30. package/dist/mcp/toolAnalytics.js +8 -0
  31. package/dist/mcp/toolAnalytics.js.map +1 -1
  32. package/dist/routes/agentVariants.d.ts.map +1 -1
  33. package/dist/routes/agentVariants.js +17 -9
  34. package/dist/routes/agentVariants.js.map +1 -1
  35. package/dist/routes/mcp.d.ts.map +1 -1
  36. package/dist/routes/mcp.js +18 -11
  37. package/dist/routes/mcp.js.map +1 -1
  38. package/dist/services/ConfigManager.d.ts +13 -0
  39. package/dist/services/ConfigManager.d.ts.map +1 -1
  40. package/dist/services/ConfigManager.js +24 -0
  41. package/dist/services/ConfigManager.js.map +1 -1
  42. package/dist/services/TelemetryService.d.ts +4 -0
  43. package/dist/services/TelemetryService.d.ts.map +1 -1
  44. package/dist/services/TelemetryService.js +19 -0
  45. package/dist/services/TelemetryService.js.map +1 -1
  46. package/dist/services/createAgentVariantsOrchestrator.d.ts +16 -0
  47. package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
  48. package/dist/services/createAgentVariantsOrchestrator.js +60 -2
  49. package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
  50. package/dist/utils/skills/claude-skill.d.ts +1 -1
  51. package/dist/utils/skills/claude-skill.d.ts.map +1 -1
  52. package/dist/utils/skills/claude-skill.js +16 -6
  53. package/dist/utils/skills/claude-skill.js.map +1 -1
  54. package/dist/utils/skills/cursor-rules.d.ts +1 -1
  55. package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
  56. package/dist/utils/skills/cursor-rules.js +16 -6
  57. package/dist/utils/skills/cursor-rules.js.map +1 -1
  58. package/dist/utils/skills/describe-motion-protocol.d.ts +1 -1
  59. package/dist/utils/skills/describe-motion-protocol.d.ts.map +1 -1
  60. package/dist/utils/skills/describe-motion-protocol.js +1 -1
  61. package/dist/utils/skills/shared-variants-protocol.d.ts +20 -2
  62. package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
  63. package/dist/utils/skills/shared-variants-protocol.js +91 -19
  64. package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
  65. package/package.json +16 -38
  66. package/src/ui/dist/assets/main-CLAqO1bm.js +656 -0
  67. package/src/ui/dist/assets/main-Ke-Q9lWa.css +1 -0
  68. package/src/ui/dist/index.html +2 -2
  69. package/src/ui/dist/assets/main-B26kBifl.js +0 -656
  70. package/src/ui/dist/assets/main-B9-DG2wa.css +0 -1
@@ -1,4 +1,4 @@
1
- export declare const CURSOR_RULES_VERSION = 32;
1
+ export declare const CURSOR_RULES_VERSION = 35;
2
2
  export declare const CURSOR_RULES_FILENAME = "rivet.mdc";
3
3
  export declare const CURSOR_RULES_CONTENT: string;
4
4
  //# sourceMappingURL=cursor-rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-rules.d.ts","sourceRoot":"","sources":["../../../src/utils/skills/cursor-rules.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,qBAAqB,cAAc,CAAC;AAuBjD,eAAO,MAAM,oBAAoB,QAwDhC,CAAC"}
1
+ {"version":3,"file":"cursor-rules.d.ts","sourceRoot":"","sources":["../../../src/utils/skills/cursor-rules.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,qBAAqB,cAAc,CAAC;AAuBjD,eAAO,MAAM,oBAAoB,QAkEhC,CAAC"}
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CURSOR_RULES_CONTENT = exports.CURSOR_RULES_FILENAME = exports.CURSOR_RULES_VERSION = void 0;
4
4
  const shared_variants_protocol_1 = require("./shared-variants-protocol");
5
- exports.CURSOR_RULES_VERSION = 32;
5
+ exports.CURSOR_RULES_VERSION = 35;
6
6
  exports.CURSOR_RULES_FILENAME = 'rivet.mdc';
7
7
  const CURSOR_RULES_VERSION_MARKER = `rivet-rules-version: ${exports.CURSOR_RULES_VERSION}`;
8
8
  const AGENT_VARIANTS_SECTION = (0, shared_variants_protocol_1.buildAgentVariantsSection)({
@@ -11,8 +11,8 @@ const AGENT_VARIANTS_SECTION = (0, shared_variants_protocol_1.buildAgentVariants
11
11
  - Read \`input.briefBody\` and \`input.target\`
12
12
  - When \`input.target\` is present, scope the change to that element/file/route and its immediate section — do not restyle the rest of the page.
13
13
  - Edit files in \`input.worktreePath\` (each variant has its own isolated worktree)
14
- - Verify the worktree diff includes CSS or markup changes before calling \`report_variant_complete\` with status \`'succeeded'\` — empty or deletion-only diffs fail QA.
15
- - Call \`report_variant_complete({ sessionId, workItemId, leaseId, attempt, status: 'succeeded' })\`. On failure, status \`'failed'\` with error description.`,
14
+ - Verify the worktree diff includes CSS or markup changes before calling \`report_work_item\` (kind \`status\`) with status \`'succeeded'\` — empty or deletion-only diffs fail QA.
15
+ - Call \`report_work_item({ kind: 'status', sessionId, workItemId, leaseId, attempt, status: 'succeeded' })\`. On failure, status \`'failed'\` with error description.`,
16
16
  step11Suffix: `When \`hasChanges: true\`, you'll see a \`VariantChangeItem\` in \`changes[]\`.`,
17
17
  nativeGenLabel: 'Task tool',
18
18
  });
@@ -24,23 +24,33 @@ const CONCURRENT_REFINE_SECTION = (0, shared_variants_protocol_1.buildConcurrent
24
24
  - Going idle after answering an unrelated question. Re-arm \`watch_for_changes\` whenever you return to the session, and drain any \`pendingVariantRequests\` first.`,
25
25
  });
26
26
  exports.CURSOR_RULES_CONTENT = `---
27
- description: Rivet — design agent for point-and-click UI changes ("open rivet", "open the visual editor") and exploring N parallel design directions ("create variants", "show me options for X", "build me X from scratch", "create a new Y app")
27
+ description: Rivet — explore multiple design directions for your web app ("/rivet", "use rivet variants", "explore with rivet", "create variants", "show me options for X", "build me X from scratch", "create a new Y app", "open rivet", "open the visual editor")
28
28
  alwaysApply: false
29
29
  ---
30
30
  <!-- ${CURSOR_RULES_VERSION_MARKER} -->
31
31
  # Rivet
32
32
 
33
- Rivet is a **design agent** with two flows: the **visual editor** (point-and-click changes to a web app including an empty or HTML-only folder, which opens in static mode) and the **agent-variants flow** (explore N parallel design directions before committing).
33
+ Rivet helps you **explore multiple design directions** for your web app. It generates parallel variants you can compare side by side, refine with the comment tool, connect design references from Pinterest or Are.na, and share or implement the direction you choose.
34
+
35
+ Rivet also has a **visual editor** flow for direct point-and-click changes to a web app (including empty or HTML-only folders, which open in static mode).
34
36
 
35
37
  > Tip: type \`@rivet.mdc\` in chat to invoke this rule manually.
36
38
 
39
+ ${shared_variants_protocol_1.RIVET_OVERVIEW}
40
+
37
41
  ${shared_variants_protocol_1.PICKING_THE_FLOW_TABLE}
38
42
 
43
+ ---
44
+
45
+ ${shared_variants_protocol_1.PROACTIVE_FIRST_DIRECTIONS_SECTION}
46
+
47
+ ---
48
+
39
49
  ## Visual Editor flow
40
50
 
41
51
  ## Starting a session
42
52
 
43
- An **empty folder, HTML-only folder, or standalone HTML file is a valid target** — \`open_visual_editor\` detects the framework and starts the right preview backend. When the user says "open rivet" / "use rivet here" in such a target, open the editor — do NOT refuse or reroute to variants because there's "no app yet."
53
+ An **empty folder, HTML-only folder, or standalone HTML file is a valid target** — \`open_visual_editor\` detects the framework and starts the right preview backend. When the user asks for a visual / point-and-click change (or explicitly asks to just open the editor) in such a target, open the editor — do NOT refuse or reroute to variants because there's "no app yet." **First-run exception:** a bare "open rivet" / "use rivet here" with no change described, while the first-run onboarding block is present, goes to **Proactive first directions** above — propose first, do not open an empty editor.
44
54
 
45
55
  1. Call \`open_visual_editor({ projectPath })\` — pass a specific HTML file as \`projectPath\` when the user names one; otherwise pass the folder. Do NOT pass \`startPort\` or any port unless the user provided a running server.
46
56
  2. If \`opened: false\`, follow \`nextStep\` / \`nextAction\`; for \`entry_path_required\`, call \`open_visual_editor\` again with the target HTML file or \`entryPath\`.
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-rules.js","sourceRoot":"","sources":["../../../src/utils/skills/cursor-rules.ts"],"names":[],"mappings":";;;AAAA,yEAKoC;AAEvB,QAAA,oBAAoB,GAAG,EAAE,CAAC;AAC1B,QAAA,qBAAqB,GAAG,WAAW,CAAC;AACjD,MAAM,2BAA2B,GAAG,wBAAwB,4BAAoB,EAAE,CAAC;AAEnF,MAAM,sBAAsB,GAAG,IAAA,oDAAyB,EAAC;IACvD,cAAc,EAAE,SAAS;IACzB,KAAK,EAAE;;;;;iKAKwJ;IAC/J,YAAY,EAAE,iFAAiF;IAC/F,cAAc,EAAE,WAAW;CAC5B,CAAC,CAAC;AAEH,MAAM,yBAAyB,GAAG,IAAA,uDAA4B,EAAC;IAC7D,cAAc,EAAE,oPAAoP;IACpQ,QAAQ,EAAE,+PAA+P;IACzQ,cAAc,EAAE;;qKAEmJ;CACpK,CAAC,CAAC;AAEU,QAAA,oBAAoB,GAAG;;;;OAI7B,2BAA2B;;;;;;;EAOhC,iDAAsB;;;;;;;;;;;;;;;;;;;;;;;;EAwBtB,wDAA6B;;;;;;;;;;;;;;;;EAgB7B,yBAAyB;;;;EAIzB,sBAAsB;CACvB,CAAC"}
1
+ {"version":3,"file":"cursor-rules.js","sourceRoot":"","sources":["../../../src/utils/skills/cursor-rules.ts"],"names":[],"mappings":";;;AAAA,yEAOoC;AAEvB,QAAA,oBAAoB,GAAG,EAAE,CAAC;AAC1B,QAAA,qBAAqB,GAAG,WAAW,CAAC;AACjD,MAAM,2BAA2B,GAAG,wBAAwB,4BAAoB,EAAE,CAAC;AAEnF,MAAM,sBAAsB,GAAG,IAAA,oDAAyB,EAAC;IACvD,cAAc,EAAE,SAAS;IACzB,KAAK,EAAE;;;;;0KAKiK;IACxK,YAAY,EAAE,iFAAiF;IAC/F,cAAc,EAAE,WAAW;CAC5B,CAAC,CAAC;AAEH,MAAM,yBAAyB,GAAG,IAAA,uDAA4B,EAAC;IAC7D,cAAc,EAAE,oPAAoP;IACpQ,QAAQ,EAAE,+PAA+P;IACzQ,cAAc,EAAE;;qKAEmJ;CACpK,CAAC,CAAC;AAEU,QAAA,oBAAoB,GAAG;;;;OAI7B,2BAA2B;;;;;;;;;EAShC,yCAAc;;EAEd,iDAAsB;;;;EAItB,6DAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BlC,wDAA6B;;;;;;;;;;;;;;;;EAgB7B,yBAAyB;;;;EAIzB,sBAAsB;CACvB,CAAC"}
@@ -6,5 +6,5 @@
6
6
  * skill; this version is trimmed for Rivet's video-input path and emits
7
7
  * the spec as `motion_guidance` metadata reported during source planning.
8
8
  */
9
- export declare const DESCRIBE_MOTION_PROTOCOL = "### Describe Motion protocol (video / motion artifact -> motion_guidance)\n\nUse this protocol when the user attaches a video, gif, screen recording, or\nframe sequence to a variants request. Pass the raw video/clip to\n`start_variants` as a `userContext` entry (`transport: 'file_path'` for a\nlocal file, `transport: 'url'` for a hosted clip). Then run this protocol\nduring source planning \u2014 on the source path Rivet hands back in the\n`source_plan` work item \u2014 and report a `describe_motion` action plus the\nstructured spec below as `motion_guidance` metadata (the spec text becomes\n`data.motionMarkdown`).\n\nIf the user provided ONLY a static image or a URL with no motion, this protocol\nis the wrong tool \u2014 report an `extract_design_system` action with\n`design_system` metadata instead.\n\n#### Step 1 \u2014 Get frames you can inspect\n\nGuessing from memory of a single playback is the most common failure mode.\nPull stills before describing anything.\n\n- **Video (.mov/.mp4/.webm):** `ffmpeg -i <input> -vf \"fps=30\" frames/%04d.png`\n to step through, or `ffmpeg -i <input> -ss <timestamp> -frames:v 1 frame.png`\n for a single frame around a state change.\n- **GIF:** `magick <input> -coalesce frames/%04d.png` (ImageMagick) for\n per-frame stills.\n- **Unknown framerate:** assume 30 or 60fps. 33ms per frame at 30fps,\n 16ms per frame at 60fps. Multiply frame count between state-change\n boundaries to get duration.\n- **Frame sequence already supplied:** read every frame. The middle frames\n carry the easing.\n\nIf you cannot extract frames in the current environment, say so explicitly in\nthe spec and mark timing / easing fields with `~estimated`.\n\n#### Step 2 \u2014 Five-phase pass\n\nRun these in order. Later phases depend on earlier observations.\n\n1. **Elements & trigger.** Which DOM nodes change between frames, what\n initiates the motion (`hover`, `click`, `focus`, `mount`, `unmount`,\n `scroll`, `intersection`, `drag`, `route change`, `state change`,\n `keypress`), and the direction (entrance / exit / hover / toggle / loop).\n2. **States.** Enumerate discrete states. Most interactions are A -> B\n or A -> B -> A. Some have intermediates (idle -> loading -> success).\n For each state, note every property that will animate.\n3. **Per-property motion.** For each animated property on each element:\n - **Property** \u2014 prefer compositor-friendly (`transform`, `opacity`).\n - **From -> to** \u2014 concrete values (`opacity: 0 -> 1`, `translateY: 8px -> 0`).\n - **Duration** \u2014 milliseconds, measured from frame count. Round to common\n UI durations when within 1 frame: 150, 200, 250, 300, 400, 500ms.\n - **Easing** \u2014 identify by shape (see easing guide below), not by guessing\n a cubic-bezier from memory.\n - **Delay** \u2014 t=0 or later?\n4. **Choreography.** How per-property animations relate across elements:\n parallel (default), sequence (B starts after A), stagger (siblings with a\n fixed offset \u2014 note interval and direction), overlap (B starts before A\n finishes \u2014 note overlap duration), anchor / transform origin if non-default.\n5. **Edge cases & quality.** Cover all of these, even if the answer is\n \"not visible in artifact \u2014 recommend default\":\n - **Reduced motion** \u2014 what `prefers-reduced-motion: reduce` should do.\n Default: skip transforms, keep opacity, shorten to ~0ms.\n - **Interrupt** \u2014 re-trigger mid-animation: snap, reverse from current,\n or queue?\n - **Exit symmetry** \u2014 is the exit the reverse of the entrance, or different?\n - **Loop** \u2014 one-shot, loop, ping-pong, or on-demand?\n - **Performance flags** \u2014 any property that would force layout\n (`height`, `width`, `top`)? Flag and suggest a transform alternative\n if visually equivalent.\n\n#### Easing identification guide\n\nWatch the speed across the animation, not just the endpoints.\n\n- **Linear** \u2014 constant speed. Mechanical-feeling. Rare in good UI.\n- **Ease-out** \u2014 fast start, slow end. Most common entrance.\n- **Ease-in** \u2014 slow start, fast end. Best for exits.\n- **Ease-in-out** \u2014 slow-fast-slow. For transitions between two non-home states.\n- **Spring** \u2014 overshoots, then settles. Look for any frame where the element\n passes its final position. Springs cross the target; ease-out approaches\n monotonically.\n- **Back-out / overshoot** \u2014 ease-out with a slight overshoot before settling.\n\n#### Library recommendation\n\nPick one based on what you observed; the downstream codegen may override.\n\n- **CSS transitions** \u2014 simple state change, single property, no interrupt\n complexity.\n- **CSS keyframes** \u2014 loops, multi-step sequences with fixed timing.\n- **Framer Motion** \u2014 springs, gestures, layout animations, exit animations\n via `AnimatePresence`, stagger via `staggerChildren`.\n- **React Spring** \u2014 physics-driven motion where spring feel matters more\n than precise timing.\n- **GSAP** \u2014 complex sequences, timeline choreography, SVG morphing.\n- **Native View Transitions API** \u2014 page / route transitions where browser\n support allows.\n\n#### Spec template (the `motion_guidance` markdown payload)\n\nAlways produce this exact shape. If a field is not observable, write\n`not visible in artifact` \u2014 do not omit the field. The content string is\nwhat you report as `motion_guidance` metadata `data.motionMarkdown`.\n\n```\n# Motion spec: <short name>\n\n## Source\n- Artifact: <filename or description>\n- Input type: video | gif | recording | frame-sequence\n- Frames inspected: <count or \"single playback only\">\n- Estimated framerate: <30 | 60 | unknown>\n\n## Trigger\n- Event: <hover | click | mount | scroll | intersection | ...>\n- Element receiving event: <selector or description>\n\n## Elements animated\n1. <element name> \u2014 role in interaction\n2. ...\n\n## States\n- A (initial): <description>\n- B (final): <description>\n- (intermediate states if any)\n\n## Per-property motion\n### <element 1>\n- \\`<property>\\`: <from> -> <to>, duration <ms>, easing <type>, delay <ms>\n- ...\n\n### <element 2>\n- ...\n\n## Choreography\n- <parallel | sequence | stagger | overlap with details>\n- Transform origin: <if non-default>\n\n## Edge cases\n- Reduced motion: <behavior>\n- Interrupt: <snap | reverse | queue>\n- Exit: <symmetric reverse | different \u2014 describe>\n- Loop: <one-shot | loop | ping-pong>\n- Performance flags: <any layout-thrashing properties>\n\n## Recommended implementation\n- Library: <css | framer-motion | gsap | react-spring | view-transitions>\n- Reason: <one line>\n\n## Confidence\n- High / Medium / Low on: <which fields>\n- Estimates flagged with ~ in the spec above\n```\n\n#### Working principles\n\n- **Numbers over adjectives.** \"Fast\" is useless; \"180ms\" is implementable.\n If you cannot get a number, write `~estimated` and a range.\n- **Frame counting beats vibes.** Snappy ~ 150-250ms; deliberate ~ 300-500ms.\n Measure when you can.\n- **Identify easing by shape, not by name.** Watch where the element sits\n at 25%, 50%, 75% of the duration. Even spacing = linear. Compressed at\n the end = ease-out.\n- **Distinguish observed from inferred.** Anything not seen in the artifact\n is inference. Mark it.\n- **One spec per interaction.** If the video shows three interactions,\n report three `describe_motion` actions (each with its own\n `motion_guidance` metadata), not one merged blob.\n\n#### Handing the spec back to Rivet\n\nReport each finished spec during source planning as a `describe_motion`\naction plus linked `motion_guidance` metadata in the `report_source_plan`\ncall:\n\n```\nactions: [\n { id: 'action_motion_1', kind: 'describe_motion', sourceIds: ['<the video userContext id>'], reason: '<why>' },\n // ... one per distinct interaction in the video\n],\nmetadata: [\n {\n id: 'meta_motion_1',\n kind: 'motion_guidance',\n sourceIds: ['<the video userContext id>'],\n actionId: 'action_motion_1',\n producedBy: 'skill',\n data: {\n motionMarkdown: '<the full spec from the template above>',\n notes: ['<one-line timing/easing summary>'],\n timings: ['<e.g. 240ms ease-out>'],\n },\n },\n]\n```\n\n**Routing.** A request that attaches a video, image, URL, file, or directory is\nsource-grounded. Pass each as a `userContext` entry to\n`start_variants({ mode: 'zero_to_one' })`; start_variants detects the raw\nuser context and runs the source-research (`source_plan`) flow automatically,\nreturning `stage: 'awaiting_source_plan'` (rather than the prompt-only\nsingle-call `work_items_ready`).\n\nstart_variants is the single fresh-project entry point \u2014 there is **no**\nseparate source-grounded kickoff tool. A prompt-only `start_variants({ mode:\n'zero_to_one' })` call (no `userContext`) takes the single-call path and\nreturns `work_items_ready` directly; adding any `userContext` switches it to\nthe multi-step source-research flow.\n\nIf the video is supplementary to an existing project (the user wants\nvariants of a specific element / file / route in their open project and\nattached a video for motion reference), use\n`start_variants({ mode: 'existing', target: ... })` with the video as a\n`userContext` entry; the raw clip is threaded into each variant's code-gen\ncontext. You may also embed the motion spec into each variant's\n`briefs[i].body`.\n\nPer-variant briefs and codegen should treat the `motion_guidance` as\nauthoritative timing / easing / choreography guidance \u2014 visual styling can\ndiverge per variant, motion fidelity should not.";
9
+ export declare const DESCRIBE_MOTION_PROTOCOL = "### Describe Motion protocol (video / motion artifact -> motion_guidance)\n\nUse this protocol when the user attaches a video, gif, screen recording, or\nframe sequence to a variants request. Pass the raw video/clip to\n`start_variants` as a `userContext` entry (`transport: 'file_path'` for a\nlocal file, `transport: 'url'` for a hosted clip). Then run this protocol\nduring source planning \u2014 on the source path Rivet hands back in the\n`source_plan` work item \u2014 and report a `describe_motion` action plus the\nstructured spec below as `motion_guidance` metadata (the spec text becomes\n`data.motionMarkdown`).\n\nIf the user provided ONLY a static image or a URL with no motion, this protocol\nis the wrong tool \u2014 report an `extract_design_system` action with\n`design_system` metadata instead.\n\n#### Step 1 \u2014 Get frames you can inspect\n\nGuessing from memory of a single playback is the most common failure mode.\nPull stills before describing anything.\n\n- **Video (.mov/.mp4/.webm):** `ffmpeg -i <input> -vf \"fps=30\" frames/%04d.png`\n to step through, or `ffmpeg -i <input> -ss <timestamp> -frames:v 1 frame.png`\n for a single frame around a state change.\n- **GIF:** `magick <input> -coalesce frames/%04d.png` (ImageMagick) for\n per-frame stills.\n- **Unknown framerate:** assume 30 or 60fps. 33ms per frame at 30fps,\n 16ms per frame at 60fps. Multiply frame count between state-change\n boundaries to get duration.\n- **Frame sequence already supplied:** read every frame. The middle frames\n carry the easing.\n\nIf you cannot extract frames in the current environment, say so explicitly in\nthe spec and mark timing / easing fields with `~estimated`.\n\n#### Step 2 \u2014 Five-phase pass\n\nRun these in order. Later phases depend on earlier observations.\n\n1. **Elements & trigger.** Which DOM nodes change between frames, what\n initiates the motion (`hover`, `click`, `focus`, `mount`, `unmount`,\n `scroll`, `intersection`, `drag`, `route change`, `state change`,\n `keypress`), and the direction (entrance / exit / hover / toggle / loop).\n2. **States.** Enumerate discrete states. Most interactions are A -> B\n or A -> B -> A. Some have intermediates (idle -> loading -> success).\n For each state, note every property that will animate.\n3. **Per-property motion.** For each animated property on each element:\n - **Property** \u2014 prefer compositor-friendly (`transform`, `opacity`).\n - **From -> to** \u2014 concrete values (`opacity: 0 -> 1`, `translateY: 8px -> 0`).\n - **Duration** \u2014 milliseconds, measured from frame count. Round to common\n UI durations when within 1 frame: 150, 200, 250, 300, 400, 500ms.\n - **Easing** \u2014 identify by shape (see easing guide below), not by guessing\n a cubic-bezier from memory.\n - **Delay** \u2014 t=0 or later?\n4. **Choreography.** How per-property animations relate across elements:\n parallel (default), sequence (B starts after A), stagger (siblings with a\n fixed offset \u2014 note interval and direction), overlap (B starts before A\n finishes \u2014 note overlap duration), anchor / transform origin if non-default.\n5. **Edge cases & quality.** Cover all of these, even if the answer is\n \"not visible in artifact \u2014 recommend default\":\n - **Reduced motion** \u2014 what `prefers-reduced-motion: reduce` should do.\n Default: skip transforms, keep opacity, shorten to ~0ms.\n - **Interrupt** \u2014 re-trigger mid-animation: snap, reverse from current,\n or queue?\n - **Exit symmetry** \u2014 is the exit the reverse of the entrance, or different?\n - **Loop** \u2014 one-shot, loop, ping-pong, or on-demand?\n - **Performance flags** \u2014 any property that would force layout\n (`height`, `width`, `top`)? Flag and suggest a transform alternative\n if visually equivalent.\n\n#### Easing identification guide\n\nWatch the speed across the animation, not just the endpoints.\n\n- **Linear** \u2014 constant speed. Mechanical-feeling. Rare in good UI.\n- **Ease-out** \u2014 fast start, slow end. Most common entrance.\n- **Ease-in** \u2014 slow start, fast end. Best for exits.\n- **Ease-in-out** \u2014 slow-fast-slow. For transitions between two non-home states.\n- **Spring** \u2014 overshoots, then settles. Look for any frame where the element\n passes its final position. Springs cross the target; ease-out approaches\n monotonically.\n- **Back-out / overshoot** \u2014 ease-out with a slight overshoot before settling.\n\n#### Library recommendation\n\nPick one based on what you observed; the downstream codegen may override.\n\n- **CSS transitions** \u2014 simple state change, single property, no interrupt\n complexity.\n- **CSS keyframes** \u2014 loops, multi-step sequences with fixed timing.\n- **Framer Motion** \u2014 springs, gestures, layout animations, exit animations\n via `AnimatePresence`, stagger via `staggerChildren`.\n- **React Spring** \u2014 physics-driven motion where spring feel matters more\n than precise timing.\n- **GSAP** \u2014 complex sequences, timeline choreography, SVG morphing.\n- **Native View Transitions API** \u2014 page / route transitions where browser\n support allows.\n\n#### Spec template (the `motion_guidance` markdown payload)\n\nAlways produce this exact shape. If a field is not observable, write\n`not visible in artifact` \u2014 do not omit the field. The content string is\nwhat you report as `motion_guidance` metadata `data.motionMarkdown`.\n\n```\n# Motion spec: <short name>\n\n## Source\n- Artifact: <filename or description>\n- Input type: video | gif | recording | frame-sequence\n- Frames inspected: <count or \"single playback only\">\n- Estimated framerate: <30 | 60 | unknown>\n\n## Trigger\n- Event: <hover | click | mount | scroll | intersection | ...>\n- Element receiving event: <selector or description>\n\n## Elements animated\n1. <element name> \u2014 role in interaction\n2. ...\n\n## States\n- A (initial): <description>\n- B (final): <description>\n- (intermediate states if any)\n\n## Per-property motion\n### <element 1>\n- \\`<property>\\`: <from> -> <to>, duration <ms>, easing <type>, delay <ms>\n- ...\n\n### <element 2>\n- ...\n\n## Choreography\n- <parallel | sequence | stagger | overlap with details>\n- Transform origin: <if non-default>\n\n## Edge cases\n- Reduced motion: <behavior>\n- Interrupt: <snap | reverse | queue>\n- Exit: <symmetric reverse | different \u2014 describe>\n- Loop: <one-shot | loop | ping-pong>\n- Performance flags: <any layout-thrashing properties>\n\n## Recommended implementation\n- Library: <css | framer-motion | gsap | react-spring | view-transitions>\n- Reason: <one line>\n\n## Confidence\n- High / Medium / Low on: <which fields>\n- Estimates flagged with ~ in the spec above\n```\n\n#### Working principles\n\n- **Numbers over adjectives.** \"Fast\" is useless; \"180ms\" is implementable.\n If you cannot get a number, write `~estimated` and a range.\n- **Frame counting beats vibes.** Snappy ~ 150-250ms; deliberate ~ 300-500ms.\n Measure when you can.\n- **Identify easing by shape, not by name.** Watch where the element sits\n at 25%, 50%, 75% of the duration. Even spacing = linear. Compressed at\n the end = ease-out.\n- **Distinguish observed from inferred.** Anything not seen in the artifact\n is inference. Mark it.\n- **One spec per interaction.** If the video shows three interactions,\n report three `describe_motion` actions (each with its own\n `motion_guidance` metadata), not one merged blob.\n\n#### Handing the spec back to Rivet\n\nReport each finished spec during source planning as a `describe_motion`\naction plus linked `motion_guidance` metadata in the `report_work_item(kind='source_plan')`\ncall:\n\n```\nactions: [\n { id: 'action_motion_1', kind: 'describe_motion', sourceIds: ['<the video userContext id>'], reason: '<why>' },\n // ... one per distinct interaction in the video\n],\nmetadata: [\n {\n id: 'meta_motion_1',\n kind: 'motion_guidance',\n sourceIds: ['<the video userContext id>'],\n actionId: 'action_motion_1',\n producedBy: 'skill',\n data: {\n motionMarkdown: '<the full spec from the template above>',\n notes: ['<one-line timing/easing summary>'],\n timings: ['<e.g. 240ms ease-out>'],\n },\n },\n]\n```\n\n**Routing.** A request that attaches a video, image, URL, file, or directory is\nsource-grounded. Pass each as a `userContext` entry to\n`start_variants({ mode: 'zero_to_one' })`; start_variants detects the raw\nuser context and runs the source-research (`source_plan`) flow automatically,\nreturning `stage: 'awaiting_source_plan'` (rather than the prompt-only\nsingle-call `work_items_ready`).\n\nstart_variants is the single fresh-project entry point \u2014 there is **no**\nseparate source-grounded kickoff tool. A prompt-only `start_variants({ mode:\n'zero_to_one' })` call (no `userContext`) takes the single-call path and\nreturns `work_items_ready` directly; adding any `userContext` switches it to\nthe multi-step source-research flow.\n\nIf the video is supplementary to an existing project (the user wants\nvariants of a specific element / file / route in their open project and\nattached a video for motion reference), use\n`start_variants({ mode: 'existing', target: ... })` with the video as a\n`userContext` entry; the raw clip is threaded into each variant's code-gen\ncontext. You may also embed the motion spec into each variant's\n`briefs[i].body`.\n\nPer-variant briefs and codegen should treat the `motion_guidance` as\nauthoritative timing / easing / choreography guidance \u2014 visual styling can\ndiverge per variant, motion fidelity should not.";
10
10
  //# sourceMappingURL=describe-motion-protocol.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"describe-motion-protocol.d.ts","sourceRoot":"","sources":["../../../src/utils/skills/describe-motion-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,49SA0NY,CAAC"}
1
+ {"version":3,"file":"describe-motion-protocol.d.ts","sourceRoot":"","sources":["../../../src/utils/skills/describe-motion-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,8+SA0NY,CAAC"}
@@ -180,7 +180,7 @@ what you report as \`motion_guidance\` metadata \`data.motionMarkdown\`.
180
180
  #### Handing the spec back to Rivet
181
181
 
182
182
  Report each finished spec during source planning as a \`describe_motion\`
183
- action plus linked \`motion_guidance\` metadata in the \`report_source_plan\`
183
+ action plus linked \`motion_guidance\` metadata in the \`report_work_item(kind='source_plan')\`
184
184
  call:
185
185
 
186
186
  \`\`\`
@@ -2,15 +2,33 @@
2
2
  * Watch → lease → act flow shared by apply and variant batches.
3
3
  * Imported by agent skill files so MCP semantics stay aligned with the bridge.
4
4
  */
5
- export declare const DURABLE_BATCH_HANDOFF_SECTION = "## Durable batch handoff (apply + variant)\n\nBoth point-and-click **apply** batches and in-editor **variant** batches use the same bridge pickup pipeline: **queued \u2192 leased \u2192 acted on**. Apply leases are released by an explicit apply ack; generated variant work is released by `report_variant_complete` when every tracked work item reaches a terminal state. The host agent must keep this loop alive whenever the visual editor is open.\n\n**One loop for both kinds:**\n\n1. `watch_for_changes({ sessionId })` \u2014 blocks until work exists. While blocked with no lease yet, bridge status is `WATCHING` (this is **not** round complete).\n2. Pickup returns `{ leaseId, requestId, kind: 'apply' | 'variant', mergedRequestIds?, \u2026 }`. Re-polling the same `requestId` is idempotent \u2014 you get the same lease back.\n3. **Act** on the leased payload:\n - `kind: 'apply'` \u2192 edit files from `sourceFiles` / `changes[]`\n - `kind: 'variant'` \u2192 `start_variants` / static refine / `continue_variants` per the batch shape\n4. **Release** the leased work only after acting:\n - apply leases \u2192 `get_pending_changes({ sessionId, message, refresh_git: true })`\n - UI-originated `variant_request` / `static_preview_refine` leases \u2192 process via `start_variants` or scoped `continue_variants({ action: 'request_work', workItemIds })`, call `report_variant_complete` for every generated item, and let the server release the bridge lease after all tracked items finish\n - Do NOT use `ack_batch` to skip or finish generated variant work; unclaimed or unfinished variant leases return a structured `variant_ack_blocked` error\n5. Immediately call `watch_for_changes` again while `hasUnfinishedWork` / `pendingVariantRequests` is non-zero.\n\n**Status semantics (do not confuse with batch lifecycle):**\n\n| Status | Meaning |\n|---|---|\n| `WATCHING` | Watch loop blocked, nothing leased yet \u2014 **keep waiting** |\n| `APPLYING` | Apply lease active, agent working |\n| `READY` | **Only after explicit apply ack** \u2014 safe for Rivet UI to clear markers |\n\n`READY` before `refresh_git` was a spurious idle pulse \u2014 ignore it. Never treat `WATCHING` as completion.\n\n**Queue-time merge:** several Sends may merge into one apply lease (`mergedRequestIds`). One agent pass + one `refresh_git` clears markers for **all** merged request ids.";
5
+ export declare const DURABLE_BATCH_HANDOFF_SECTION = "## Durable batch handoff (apply + variant)\n\nBoth point-and-click **apply** batches and in-editor **variant** batches use the same bridge pickup pipeline: **queued \u2192 leased \u2192 acted on**. Apply leases are released by an explicit apply ack; generated variant work is released by `report_work_item` (kind `status`) when every tracked work item reaches a terminal state. The host agent must keep this loop alive whenever the visual editor is open.\n\n**One loop for both kinds:**\n\n1. `watch_for_changes({ sessionId })` \u2014 blocks until work exists. While blocked with no lease yet, bridge status is `WATCHING` (this is **not** round complete).\n2. Pickup returns `{ leaseId, requestId, kind: 'apply' | 'variant', mergedRequestIds?, \u2026 }`. Re-polling the same `requestId` is idempotent \u2014 you get the same lease back.\n3. **Act** on the leased payload:\n - `kind: 'apply'` \u2192 edit files from `sourceFiles` / `changes[]`\n - `kind: 'variant'` \u2192 `start_variants` / static refine / `continue_variants` per the batch shape\n4. **Release** the leased work only after acting:\n - apply leases \u2192 `get_pending_changes({ sessionId, message, refresh_git: true })`\n - UI-originated `variant_request` / `static_preview_refine` leases \u2192 process via `start_variants` or scoped `continue_variants({ action: 'request_work', workItemIds })`, call `report_work_item(kind='status')` for every generated item, and let the server release the bridge lease after all tracked items finish\n - Do NOT use `ack_batch` to skip or finish generated variant work; unclaimed or unfinished variant leases return a structured `variant_ack_blocked` error\n5. Immediately call `watch_for_changes` again while `hasUnfinishedWork` / `pendingVariantRequests` is non-zero.\n\n**Status semantics (do not confuse with batch lifecycle):**\n\n| Status | Meaning |\n|---|---|\n| `WATCHING` | Watch loop blocked, nothing leased yet \u2014 **keep waiting** |\n| `APPLYING` | Apply lease active, agent working |\n| `READY` | **Only after explicit apply ack** \u2014 safe for Rivet UI to clear markers |\n\n`READY` before `refresh_git` was a spurious idle pulse \u2014 ignore it. Never treat `WATCHING` as completion.\n\n**Queue-time merge:** several Sends may merge into one apply lease (`mergedRequestIds`). One agent pass + one `refresh_git` clears markers for **all** merged request ids.";
6
6
  /**
7
7
  * Canonical brief format instruction — single source of truth.
8
8
  * Imported by claude-skill.ts, cursor-rules.ts, and tools.ts so the
9
9
  * wording can never silently diverge between agents.
10
10
  */
11
11
  export declare const BRIEF_FORMAT_INSTRUCTION: string;
12
+ /**
13
+ * User-facing overview — what to tell the user when they ask what Rivet does
14
+ * or when the agent first opens the editor.
15
+ */
16
+ export declare const RIVET_OVERVIEW = "## What Rivet does\n\nRivet helps you **explore multiple design directions** for your web app. It generates parallel variants you can compare side by side, refine with precision, and share or implement.\n\n### How to use Rivet\n\n1. **Start from your coding agent.** Use `/rivet` in Claude Code, or tell your agent \"Use Rivet variants\" or \"Explore with Rivet\" along with your design request.\n2. **Connect design references** (optional). Click **Connect design references** in the editor to link your Pinterest or Are.na account. Include relevant pins or boards and Rivet will extract design context from them to inform the variants it generates.\n3. **Refine with the comment tool.** Select any part of the UI and use the comment tool to make more precise variants of that section, or leave comments describing what you'd like to change within a variant.\n4. **Share or implement.** When you're happy, click the **Share** button to get a shareable link you can send to a collaborator \u2014 or share it back to your coding agent to implement the chosen direction.";
12
17
  /** Routing table — identical in every agent skill file */
13
- export declare const PICKING_THE_FLOW_TABLE = "## Picking the flow\n\n| User says | Flow |\n|---|---|\n| \"open rivet\", \"use rivet here\", \"make a visual change to X\" \u2014 **including in an empty or HTML-only folder** | **Visual editor** (below). An empty / HTML-only directory is a valid target \u2014 it opens in **static mode** (no dev server). Do NOT reroute to variants or refuse just because there's no app/dev server yet. |\n| \"create variants of X\", \"show me options for X\", \"explore approaches to X\" | **Agent variants \u2014 existing project** (`start_variants`, `mode='existing'`) |\n| \"build me a settings page from scratch\", \"add a feature for Y\" | **Agent variants \u2014 existing project** (`start_variants`, no `target`) |\n| \"create a new Vite todo app\", \"scaffold a fresh dashboard\" | **Agent variants \u2014 fresh project** (`start_variants`, `mode='zero_to_one'`) |\n| \"build me a dashboard like stripe.com\", \"use this URL as inspiration\" | **Agent variants \u2014 fresh, source-grounded** (`start_variants`, `mode='zero_to_one'`, with `userContext`) |";
18
+ export declare const PICKING_THE_FLOW_TABLE = "## Picking the flow\n\n| User says | Flow |\n|---|---|\n| \"/rivet\", \"use rivet variants\", \"explore with rivet\", \"show me design options for X\", \"create variants of X\", \"show me options for X\", \"explore approaches to X\" | **Agent variants \u2014 existing project** (`start_variants`, `mode='existing'`) |\n| \"build me a settings page from scratch\", \"add a feature for Y\" | **Agent variants \u2014 existing project** (`start_variants`, no `target`) |\n| \"create a new Vite todo app\", \"scaffold a fresh dashboard\" | **Agent variants \u2014 fresh project** (`start_variants`, `mode='zero_to_one'`) |\n| \"build me a dashboard like stripe.com\", \"use this URL as inspiration\" | **Agent variants \u2014 fresh, source-grounded** (`start_variants`, `mode='zero_to_one'`, with `userContext`) |\n| \"make a visual change to X\", \"tweak this button\", \"open the editor so I can click around\" \u2014 **including in an empty or HTML-only folder** | **Visual editor** (below). An empty / HTML-only directory is a valid target \u2014 it opens in **static mode** (no dev server). Do NOT reroute to variants or refuse just because there's no app/dev server yet. |\n| \"open rivet\", \"use rivet here\" \u2014 with **no** specific change described yet, **and** the server instructions include the first-run onboarding block | **Proactive first directions** (below) \u2014 orient on the project, propose 3 distinct directions, and open the editor already generating once the user picks. Without that first-run block, a bare open goes to the **Visual editor** instead. |";
19
+ /**
20
+ * First-run onboarding flow. When the user opens Rivet without describing a
21
+ * change, lead with a proposal instead of a blank editor: orient cheaply on the
22
+ * project, propose 3 distinct directions in chat, and only open the editor once
23
+ * the user picks — so it opens already generating, never empty.
24
+ *
25
+ * This is the one entry flow that PAUSES for confirmation before generating
26
+ * (everywhere else reporting briefs starts directions immediately). It reuses
27
+ * the on-demand brief logic + `start_variants({ mode: 'existing' })` — the only
28
+ * new behaviour is the proactive trigger, a bounded orientation read, and the
29
+ * text proposal + confirmation gate.
30
+ */
31
+ export declare const PROACTIVE_FIRST_DIRECTIONS_SECTION = "## Proactive first directions\n\n**Only do this when the connect-time server instructions include the first-run onboarding block** (\"First Rivet session \u2014 lead with a proposal\"). That block appears only until the user has run variants once; on later sessions (or if it is absent) a bare open goes straight to the **Visual Editor flow** \u2014 do NOT propose.\n\n**Also skip it once the user has kicked off any variants run in this session.** The onboarding block is injected once at connect and is not refreshed mid-session, so it can linger after the user's first run \u2014 if you have already started variants (or just did), treat the block as spent and route a later bare open to the Visual Editor flow instead of proposing again.\n\nWhen the user opens Rivet with **no change or direction described yet** \u2014 a bare \"open rivet\" / \"use rivet here\" on that first session \u2014 do NOT open an empty editor and tell them to go type a request. Lead with a concrete proposal: glance at their project, suggest **3 distinct directions** for one surface, and open the editor only once they pick (so it opens with variants already streaming, never blank).\n\nThis is the ONE entry flow that pauses for confirmation before generating. Everywhere else in the variants flow, reporting briefs starts the directions immediately \u2014 here you propose first and wait.\n\n### 1. Orient cheaply \u2014 do NOT crawl the repo\n\nRead only enough to name ONE surface and describe its current visual character. There is no fixed file list and no file count to hit \u2014 there is a goal and a budget:\n\n- **Goal:** be able to state what the main surface is (framework, layout, key sections) and its current design character (light/dark, palette, density, mood).\n- **Cheapest high-signal reads first:** `package.json` (framework), a top-level glance at the `app`/`pages`/`src` or routes directory (candidate surfaces), and the theme \u2014 `tailwind.config`, the `:root` CSS variables, or `globals.css`. The theme is usually ONE file and reveals almost the entire design character.\n- **Then** read the single surface you'll propose for \u2014 the route/page/component the editor would render at its entry. Usually one file.\n- **Stop the moment you can name the surface + its character.** Do NOT follow imports down the tree, and do NOT read `node_modules`, tests, build output, or config beyond `package.json`. A handful of files, seconds not minutes.\n- If you genuinely cannot characterize a surface (empty / HTML-only folder, or an unreadable project), skip the deep read and propose along generic design levers (typography, color/mood, layout/density) \u2014 say that's what you did rather than over-reading to compensate.\n\n### 2. Draft 3 distinct directions\n\nUse the same brief discipline as the on-demand flow, framed to NAME the change (clearer for a first-time user than vibe words):\n- **Label:** a plain \u2264 4-word title that names what the direction changes (e.g. \"Editorial serif type\", \"Warm light theme\", \"Dense command layout\"). No em-dash / en-dash / colon compounds; not a vibe word.\n- **Body:** exactly ONE sentence, \u2264 12 words, describing the direction and any scope it respects.\n- **Each direction MUST lead with a DIFFERENT dominant lever** \u2014 e.g. one leads with typography, one with color/mood, one with layout/density \u2014 so the three render as visibly different results, not three flavors of \"nicer.\" Adapt every label and body to what you actually read; generic copy that could apply to any project is a failure.\n\n### 3. Propose in chat and NAME your assumption\n\nPresent the 3 directions as PLAIN TEXT (no fabricated UI, no browser tab, no URL). State which surface you looked at so a wrong guess is a one-line correction, and offer the escape hatches:\n\n> I looked at your home screen (`app/page.tsx`). Here are 3 directions I'd explore:\n> \u2022 **<label>** \u2014 <body>\n> \u2022 **<label>** \u2014 <body>\n> \u2022 **<label>** \u2014 <body>\n> Want me to run all 3? (Or point me at a different screen, or just open the editor so you can click around.)\n\nHandle the reply:\n- **\"run them\" / \"yes\" / picks a subset** \u2192 go to step 4 (drop any directions they didn't want).\n- **\"no, the <other> screen\"** \u2192 re-orient on that surface (cheap) and re-propose.\n- **\"just let me click around\" / any point-and-click request** \u2192 this is the Visual Editor flow: call `open_visual_editor` and follow it. Do NOT force a variants kickoff.\n\n### 4. On confirm \u2014 kick off; the editor opens already generating\n\nCall `start_variants({ mode: 'existing', briefs })` with the confirmed directions. There is no user prompt to pass verbatim here, so synthesize a short `prompt` from the surface you proposed for (e.g. \"Explore 3 directions for the home screen\"). `start_variants` detects the framework, opens the editor, and starts every direction \u2014 so the editor appears with variants already streaming, never empty. From here, follow **Agent Variants flow \u2192 Sub-flow A** from step 2 onward (parallel code-gen, ready, watch, apply), and keep the `watch_for_changes` loop alive per `editorNextAction`.";
14
32
  /**
15
33
  * Coordinator + elastic-worker protocol for handling the user's IN-EDITOR
16
34
  * changes (comments / "Apply" tweaks / "Vary" requests) concurrently, instead
@@ -1 +1 @@
1
- {"version":3,"file":"shared-variants-protocol.d.ts","sourceRoot":"","sources":["../../../src/utils/skills/shared-variants-protocol.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,6BAA6B,40EA2BqI,CAAC;AAEhL;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAIgF,CAAC;AAEtH,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,8hCAQwJ,CAAC;AAE5L;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB;8CAC0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB;;uCAEmC;IACnC,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CA8BT;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAkHT"}
1
+ {"version":3,"file":"shared-variants-protocol.d.ts","sourceRoot":"","sources":["../../../src/utils/skills/shared-variants-protocol.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,6BAA6B,61EA2BqI,CAAC;AAEhL;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAIgF,CAAC;AAEtH;;;GAGG;AACH,eAAO,MAAM,cAAc,ijCASgL,CAAC;AAE5M,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,8iDASkW,CAAC;AAEtY;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kCAAkC,6kKA4CoiB,CAAC;AAEplB;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB;8CAC0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB;;uCAEmC;IACnC,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CA8BT;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAkHT"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PICKING_THE_FLOW_TABLE = exports.BRIEF_FORMAT_INSTRUCTION = exports.DURABLE_BATCH_HANDOFF_SECTION = void 0;
3
+ exports.PROACTIVE_FIRST_DIRECTIONS_SECTION = exports.PICKING_THE_FLOW_TABLE = exports.RIVET_OVERVIEW = exports.BRIEF_FORMAT_INSTRUCTION = exports.DURABLE_BATCH_HANDOFF_SECTION = void 0;
4
4
  exports.buildConcurrentRefineSection = buildConcurrentRefineSection;
5
5
  exports.buildAgentVariantsSection = buildAgentVariantsSection;
6
6
  const describe_motion_protocol_1 = require("./describe-motion-protocol");
@@ -10,7 +10,7 @@ const describe_motion_protocol_1 = require("./describe-motion-protocol");
10
10
  */
11
11
  exports.DURABLE_BATCH_HANDOFF_SECTION = `## Durable batch handoff (apply + variant)
12
12
 
13
- Both point-and-click **apply** batches and in-editor **variant** batches use the same bridge pickup pipeline: **queued → leased → acted on**. Apply leases are released by an explicit apply ack; generated variant work is released by \`report_variant_complete\` when every tracked work item reaches a terminal state. The host agent must keep this loop alive whenever the visual editor is open.
13
+ Both point-and-click **apply** batches and in-editor **variant** batches use the same bridge pickup pipeline: **queued → leased → acted on**. Apply leases are released by an explicit apply ack; generated variant work is released by \`report_work_item\` (kind \`status\`) when every tracked work item reaches a terminal state. The host agent must keep this loop alive whenever the visual editor is open.
14
14
 
15
15
  **One loop for both kinds:**
16
16
 
@@ -21,7 +21,7 @@ Both point-and-click **apply** batches and in-editor **variant** batches use the
21
21
  - \`kind: 'variant'\` → \`start_variants\` / static refine / \`continue_variants\` per the batch shape
22
22
  4. **Release** the leased work only after acting:
23
23
  - apply leases → \`get_pending_changes({ sessionId, message, refresh_git: true })\`
24
- - UI-originated \`variant_request\` / \`static_preview_refine\` leases → process via \`start_variants\` or scoped \`continue_variants({ action: 'request_work', workItemIds })\`, call \`report_variant_complete\` for every generated item, and let the server release the bridge lease after all tracked items finish
24
+ - UI-originated \`variant_request\` / \`static_preview_refine\` leases → process via \`start_variants\` or scoped \`continue_variants({ action: 'request_work', workItemIds })\`, call \`report_work_item(kind='status')\` for every generated item, and let the server release the bridge lease after all tracked items finish
25
25
  - Do NOT use \`ack_batch\` to skip or finish generated variant work; unclaimed or unfinished variant leases return a structured \`variant_ack_blocked\` error
26
26
  5. Immediately call \`watch_for_changes\` again while \`hasUnfinishedWork\` / \`pendingVariantRequests\` is non-zero.
27
27
 
@@ -45,16 +45,88 @@ exports.BRIEF_FORMAT_INSTRUCTION = 'Label: ≤ 4 words, a plain standalone title
45
45
  'NEVER a "Title — descriptor" compound: no em dashes, en dashes, or colons in the label — any descriptor belongs in the body. ' +
46
46
  'Body: exactly ONE sentence, ≤ 12 words — a single evocative descriptor of the direction ' +
47
47
  '(e.g. "Apple-style spring physics with ambient blur and soft edges"). No bullet points, no lists, no line breaks.';
48
+ /**
49
+ * User-facing overview — what to tell the user when they ask what Rivet does
50
+ * or when the agent first opens the editor.
51
+ */
52
+ exports.RIVET_OVERVIEW = `## What Rivet does
53
+
54
+ Rivet helps you **explore multiple design directions** for your web app. It generates parallel variants you can compare side by side, refine with precision, and share or implement.
55
+
56
+ ### How to use Rivet
57
+
58
+ 1. **Start from your coding agent.** Use \`/rivet\` in Claude Code, or tell your agent "Use Rivet variants" or "Explore with Rivet" along with your design request.
59
+ 2. **Connect design references** (optional). Click **Connect design references** in the editor to link your Pinterest or Are.na account. Include relevant pins or boards and Rivet will extract design context from them to inform the variants it generates.
60
+ 3. **Refine with the comment tool.** Select any part of the UI and use the comment tool to make more precise variants of that section, or leave comments describing what you'd like to change within a variant.
61
+ 4. **Share or implement.** When you're happy, click the **Share** button to get a shareable link you can send to a collaborator — or share it back to your coding agent to implement the chosen direction.`;
48
62
  /** Routing table — identical in every agent skill file */
49
63
  exports.PICKING_THE_FLOW_TABLE = `## Picking the flow
50
64
 
51
65
  | User says | Flow |
52
66
  |---|---|
53
- | "open rivet", "use rivet here", "make a visual change to X" **including in an empty or HTML-only folder** | **Visual editor** (below). An empty / HTML-only directory is a valid targetit opens in **static mode** (no dev server). Do NOT reroute to variants or refuse just because there's no app/dev server yet. |
54
- | "create variants of X", "show me options for X", "explore approaches to X" | **Agent variants — existing project** (\`start_variants\`, \`mode='existing'\`) |
67
+ | "/rivet", "use rivet variants", "explore with rivet", "show me design options for X", "create variants of X", "show me options for X", "explore approaches to X" | **Agent variantsexisting project** (\`start_variants\`, \`mode='existing'\`) |
55
68
  | "build me a settings page from scratch", "add a feature for Y" | **Agent variants — existing project** (\`start_variants\`, no \`target\`) |
56
69
  | "create a new Vite todo app", "scaffold a fresh dashboard" | **Agent variants — fresh project** (\`start_variants\`, \`mode='zero_to_one'\`) |
57
- | "build me a dashboard like stripe.com", "use this URL as inspiration" | **Agent variants — fresh, source-grounded** (\`start_variants\`, \`mode='zero_to_one'\`, with \`userContext\`) |`;
70
+ | "build me a dashboard like stripe.com", "use this URL as inspiration" | **Agent variants — fresh, source-grounded** (\`start_variants\`, \`mode='zero_to_one'\`, with \`userContext\`) |
71
+ | "make a visual change to X", "tweak this button", "open the editor so I can click around" — **including in an empty or HTML-only folder** | **Visual editor** (below). An empty / HTML-only directory is a valid target — it opens in **static mode** (no dev server). Do NOT reroute to variants or refuse just because there's no app/dev server yet. |
72
+ | "open rivet", "use rivet here" — with **no** specific change described yet, **and** the server instructions include the first-run onboarding block | **Proactive first directions** (below) — orient on the project, propose 3 distinct directions, and open the editor already generating once the user picks. Without that first-run block, a bare open goes to the **Visual editor** instead. |`;
73
+ /**
74
+ * First-run onboarding flow. When the user opens Rivet without describing a
75
+ * change, lead with a proposal instead of a blank editor: orient cheaply on the
76
+ * project, propose 3 distinct directions in chat, and only open the editor once
77
+ * the user picks — so it opens already generating, never empty.
78
+ *
79
+ * This is the one entry flow that PAUSES for confirmation before generating
80
+ * (everywhere else reporting briefs starts directions immediately). It reuses
81
+ * the on-demand brief logic + `start_variants({ mode: 'existing' })` — the only
82
+ * new behaviour is the proactive trigger, a bounded orientation read, and the
83
+ * text proposal + confirmation gate.
84
+ */
85
+ exports.PROACTIVE_FIRST_DIRECTIONS_SECTION = `## Proactive first directions
86
+
87
+ **Only do this when the connect-time server instructions include the first-run onboarding block** ("First Rivet session — lead with a proposal"). That block appears only until the user has run variants once; on later sessions (or if it is absent) a bare open goes straight to the **Visual Editor flow** — do NOT propose.
88
+
89
+ **Also skip it once the user has kicked off any variants run in this session.** The onboarding block is injected once at connect and is not refreshed mid-session, so it can linger after the user's first run — if you have already started variants (or just did), treat the block as spent and route a later bare open to the Visual Editor flow instead of proposing again.
90
+
91
+ When the user opens Rivet with **no change or direction described yet** — a bare "open rivet" / "use rivet here" on that first session — do NOT open an empty editor and tell them to go type a request. Lead with a concrete proposal: glance at their project, suggest **3 distinct directions** for one surface, and open the editor only once they pick (so it opens with variants already streaming, never blank).
92
+
93
+ This is the ONE entry flow that pauses for confirmation before generating. Everywhere else in the variants flow, reporting briefs starts the directions immediately — here you propose first and wait.
94
+
95
+ ### 1. Orient cheaply — do NOT crawl the repo
96
+
97
+ Read only enough to name ONE surface and describe its current visual character. There is no fixed file list and no file count to hit — there is a goal and a budget:
98
+
99
+ - **Goal:** be able to state what the main surface is (framework, layout, key sections) and its current design character (light/dark, palette, density, mood).
100
+ - **Cheapest high-signal reads first:** \`package.json\` (framework), a top-level glance at the \`app\`/\`pages\`/\`src\` or routes directory (candidate surfaces), and the theme — \`tailwind.config\`, the \`:root\` CSS variables, or \`globals.css\`. The theme is usually ONE file and reveals almost the entire design character.
101
+ - **Then** read the single surface you'll propose for — the route/page/component the editor would render at its entry. Usually one file.
102
+ - **Stop the moment you can name the surface + its character.** Do NOT follow imports down the tree, and do NOT read \`node_modules\`, tests, build output, or config beyond \`package.json\`. A handful of files, seconds not minutes.
103
+ - If you genuinely cannot characterize a surface (empty / HTML-only folder, or an unreadable project), skip the deep read and propose along generic design levers (typography, color/mood, layout/density) — say that's what you did rather than over-reading to compensate.
104
+
105
+ ### 2. Draft 3 distinct directions
106
+
107
+ Use the same brief discipline as the on-demand flow, framed to NAME the change (clearer for a first-time user than vibe words):
108
+ - **Label:** a plain ≤ 4-word title that names what the direction changes (e.g. "Editorial serif type", "Warm light theme", "Dense command layout"). No em-dash / en-dash / colon compounds; not a vibe word.
109
+ - **Body:** exactly ONE sentence, ≤ 12 words, describing the direction and any scope it respects.
110
+ - **Each direction MUST lead with a DIFFERENT dominant lever** — e.g. one leads with typography, one with color/mood, one with layout/density — so the three render as visibly different results, not three flavors of "nicer." Adapt every label and body to what you actually read; generic copy that could apply to any project is a failure.
111
+
112
+ ### 3. Propose in chat and NAME your assumption
113
+
114
+ Present the 3 directions as PLAIN TEXT (no fabricated UI, no browser tab, no URL). State which surface you looked at so a wrong guess is a one-line correction, and offer the escape hatches:
115
+
116
+ > I looked at your home screen (\`app/page.tsx\`). Here are 3 directions I'd explore:
117
+ > • **<label>** — <body>
118
+ > • **<label>** — <body>
119
+ > • **<label>** — <body>
120
+ > Want me to run all 3? (Or point me at a different screen, or just open the editor so you can click around.)
121
+
122
+ Handle the reply:
123
+ - **"run them" / "yes" / picks a subset** → go to step 4 (drop any directions they didn't want).
124
+ - **"no, the <other> screen"** → re-orient on that surface (cheap) and re-propose.
125
+ - **"just let me click around" / any point-and-click request** → this is the Visual Editor flow: call \`open_visual_editor\` and follow it. Do NOT force a variants kickoff.
126
+
127
+ ### 4. On confirm — kick off; the editor opens already generating
128
+
129
+ Call \`start_variants({ mode: 'existing', briefs })\` with the confirmed directions. There is no user prompt to pass verbatim here, so synthesize a short \`prompt\` from the surface you proposed for (e.g. "Explore 3 directions for the home screen"). \`start_variants\` detects the framework, opens the editor, and starts every direction — so the editor appears with variants already streaming, never empty. From here, follow **Agent Variants flow → Sub-flow A** from step 2 onward (parallel code-gen, ready, watch, apply), and keep the \`watch_for_changes\` loop alive per \`editorNextAction\`.`;
58
130
  /**
59
131
  * Coordinator + elastic-worker protocol for handling the user's IN-EDITOR
60
132
  * changes (comments / "Apply" tweaks / "Vary" requests) concurrently, instead
@@ -78,18 +150,18 @@ Once variants are live in the editor, the user fires changes as they go — an "
78
150
  2. When the response is \`kind: 'static_preview_refine'\`, read **\`response.workItemIds\`** — the exact work items the server created for THIS batch — and \`response.applyGuide\` (fork vs in-place).
79
151
  3. ${opts.dispatchWorker} ${opts.loopBack}
80
152
  4. Keep a bounded pool — at most \`MAX_WORKERS\` (≈4) in flight — and a \`worker → workItemIds\` map. When the pool is full, just keep calling \`watch_for_changes\`; the extra batches wait in the server's FIFO (backpressure is enforced server-side, cap 16) and you dispatch them as workers free up.
81
- 5. After each worker finishes, do **not** call \`ack_batch\`. Each worker's \`report_variant_complete\` calls are the completion signal; once all tracked work items finish, the server releases the bridge lease. Then re-watch.
153
+ 5. After each worker finishes, do **not** call \`ack_batch\`. Each worker's \`report_work_item\` (kind \`status\`) calls are the completion signal; once all tracked work items finish, the server releases the bridge lease. Then re-watch.
82
154
 
83
155
  **Worker (one per batch):**
84
- - Calls \`continue_variants({ action: 'request_work', workItemIds })\` with EXACTLY its batch's ids — this leases only those, so workers never steal each other's work. Use the \`leaseId\` from this response on every \`report_variant_complete\`.
85
- - For each leased item, follows \`applyGuide\`: **fork** → generate a NEW sibling variation of \`input.currentHtml\` applying \`input.instruction\` (with a synthesized \`title\`/\`description\`); **in-place** → edit \`input.currentHtml\` to apply \`input.instruction\` and keep the variant's name. Then \`report_variant_complete\` with the full updated \`output.html\`.
156
+ - Calls \`continue_variants({ action: 'request_work', workItemIds })\` with EXACTLY its batch's ids — this leases only those, so workers never steal each other's work. Use the \`leaseId\` from this response on every \`report_work_item(kind='status')\`.
157
+ - For each leased item, follows \`applyGuide\`: **fork** → generate a NEW sibling variation of \`input.currentHtml\` applying \`input.instruction\` (with a synthesized \`title\`/\`description\`); **in-place** → edit \`input.currentHtml\` to apply \`input.instruction\` and keep the variant's name. Then \`report_work_item(kind='status')\` with the full updated \`output.html\`.
86
158
  - Sends \`status: 'running'\` heartbeats for slow items, and on \`{ aborted: true }\` from any report it stops that item immediately (no retry) and exits.
87
159
 
88
160
  **Coalescing — dispatch exactly what the server gives you, never split or merge:**
89
161
  - Repeated "Apply" tweaks to the SAME variant are **folded server-side** into ONE in-place refine work item, so N tweaks to one card arrive as ONE \`workItemId\` → ONE worker. Distinct variants and "Vary" forks arrive as separate ids → separate workers in parallel. Don't second-guess this; one worker per \`workItemIds\` batch is always correct.
90
162
 
91
163
  **Cancellation ("clipping" a superseded change):**
92
- - The iframe calls \`cancel_variant\` itself when the user cancels a card — you don't. The affected worker's next heartbeat / report then returns \`{ aborted: true }\` and it stops. \`response.rejectedRefinements\` lists targets the server dropped (already sent / no longer editable) — tell the user those were skipped; never retry them.
164
+ - The iframe calls \`cancel_variants\` (with the card's \`variantId\`) itself when the user cancels a card — you don't. The affected worker's next heartbeat / report then returns \`{ aborted: true }\` and it stops. \`response.rejectedRefinements\` lists targets the server dropped (already sent / no longer editable) — tell the user those were skipped; never retry them.
93
165
 
94
166
  **Do NOT stop and ask "keep watching?" in this flow** — keep the coordinator loop alive so every change is picked up instantly. (That stop-and-ask handshake is only for the plain point-and-click diff-apply path.)
95
167
 
@@ -128,13 +200,13 @@ There are three sub-flows. Pick by project state:
128
200
 
129
201
  2. ${opts.step9}
130
202
 
131
- **Verify CSS or markup changes before reporting success.** For existing-project \`code_gen\` work items, inspect the worktree diff and only call \`report_variant_complete\` with \`status: 'succeeded'\` once the diff adds styling, components, or structured markup. Empty or deletion-only diffs fail QA; Rivet re-leases the work item once with \`input.qaRetry\` so you can regenerate.
203
+ **Verify CSS or markup changes before reporting success.** For existing-project \`code_gen\` work items, inspect the worktree diff and only call \`report_work_item\` (kind \`status\`) with \`status: 'succeeded'\` once the diff adds styling, components, or structured markup. Empty or deletion-only diffs fail QA; Rivet re-leases the work item once with \`input.qaRetry\` so you can regenerate.
132
204
 
133
- **The FIRST LINE of each variant's output stream MUST be a ≤4-word label** (matching the \`BRIEF_FORMAT_INSTRUCTION\` shape — e.g. "Spring blur", "Linear sharp") so the user recognises the direction as variants stream in. The code body follows. Use the \`leaseId\` from the start_variants response on every \`report_variant_complete\` call.
205
+ **The FIRST LINE of each variant's output stream MUST be a ≤4-word label** (matching the \`BRIEF_FORMAT_INSTRUCTION\` shape — e.g. "Spring blur", "Linear sharp") so the user recognises the direction as variants stream in. The code body follows. Use the \`leaseId\` from the start_variants response on every \`report_work_item(kind='status')\` call.
134
206
 
135
207
  3. **When all variants reach \`stage: 'ready'\` or \`'degraded'\`, tell the user the variants are ready** and explain how to compare them. Each variant has its own dev server running in an isolated worktree. The Rivet iframe shows a chip at the bottom-center: prev/label/next/check/dismiss. The user cycles between the live, running variants by clicking prev/next (the iframe re-mounts onto the variant's dev server in ~50ms via proxy retarget). When they like one, they click the check on the chip — that commits the variant.
136
208
 
137
- You do NOT need to print diffs in chat. The user picks visually in the iframe. You also do NOT need to call \`cancel_variant\` yourself — the iframe surfaces a cancel button per variant card, and the UI calls \`cancel_variant\` directly when the user clicks it.
209
+ You do NOT need to print diffs in chat. The user picks visually in the iframe. You also do NOT need to call \`cancel_variants\` yourself — the iframe surfaces a cancel button per variant card, and the UI calls \`cancel_variants({ sessionId, variantId })\` directly when the user clicks it.
138
210
 
139
211
  4. **Watch for the user's pick.** Use the structured \`editorNextAction\` when present; otherwise use the active visual-editor session returned by \`open_visual_editor\`. That \`watch_for_changes\` call blocks until the user clicks the check on the chip. Poll \`get_pending_changes\` only as a manual fallback for hosts that cannot block.
140
212
  ${opts.step11Suffix}
@@ -161,7 +233,7 @@ For brand-new projects the user describes from scratch ("build me a Vite todo ap
161
233
 
162
234
  Response: \`{ sessionId, stage: 'work_items_ready', mode: 'zero_to_one', leaseId, leaseTtlMs, variants: [...], scaffoldBaseWorkItemId, destinationPath, visualEditor?, editorNextAction? }\`. The server opened the editor for you if \`visualEditor\` is present — share \`visualEditor.url\` with the user immediately ("Generating variants — watch here: <url>"). Skip the manual \`open_visual_editor\` step here because the zero-to-one destination is a brand-new directory the server derives. If \`editorNextAction\` is present, keep that structured \`watch_for_changes\` loop alive on \`visualEditor.sessionId\`. This applies ONLY to the not-yet-created zero-to-one destination. An **existing** empty or HTML-only folder is a perfectly valid \`open_visual_editor\` target (it opens in static mode) — do not generalize this skip to "empty dirs can't be opened." Each \`variants[i].workItem\` carries \`input\` and \`attempt\`.
163
235
 
164
- 2. **From here, follow Sub-flow A steps 2-5** (parallel code-gen with first-line label using each variant's \`workItem.input.worktreePath\` and the shared \`leaseId\`, then ready, watch, apply). The work items are \`static_preview\` for zero-to-one — agent output must be passed to \`report_variant_complete\` as a JSON **object** with shape \`{ html: string, css?: string, js?: string }\` (self-contained HTML, no React/Vite-only imports). Do NOT stringify it — pass \`output: { html: "<!doctype html>..." }\`, not \`output: "{\\"html\\": \\"...\\"}"\`. On commit, the apply payload is \`payload.kind === 'project-created'\` — the server materialized the chosen variant to \`destinationPath\`.
236
+ 2. **From here, follow Sub-flow A steps 2-5** (parallel code-gen with first-line label using each variant's \`workItem.input.worktreePath\` and the shared \`leaseId\`, then ready, watch, apply). The work items are \`static_preview\` for zero-to-one — agent output must be passed to \`report_work_item(kind='status')\` as a JSON **object** with shape \`{ html: string, css?: string, js?: string }\` (self-contained HTML, no React/Vite-only imports). Do NOT stringify it — pass \`output: { html: "<!doctype html>..." }\`, not \`output: "{\\"html\\": \\"...\\"}"\`. On commit, the apply payload is \`payload.kind === 'project-created'\` — the server materialized the chosen variant to \`destinationPath\`.
165
237
 
166
238
  ---
167
239
 
@@ -191,9 +263,9 @@ Use the same \`start_variants({ mode: 'zero_to_one' })\` entry point as Sub-flow
191
263
  - Every reported action MUST have matching metadata linked by \`actionId\`; otherwise Rivet rejects the report. Use the stable \`id\` values from \`input.userContext\` as \`sourceIds\`.
192
264
  - \`executionPlan.mode\`: \`vite_app\` for requests needing large assets / Three.js / package dependencies / routing; \`static_preview\` for self-contained HTML/CSS/JS prototypes. If ambiguous, set \`executionPlan.userQuestion\` instead of guessing — Rivet surfaces it as a clarification blocker.
193
265
 
194
- 3. **Call \`report_source_plan\`** with \`{ sessionId, workItemId, leaseId, attempt, sourcePlan: { actions, metadata, executionPlan, bindings? } }\`. Response: \`{ stage: 'awaiting_briefs', briefWorkItem, executionPlan, nextAction: 'report_variant_briefs' }\`.
266
+ 3. **Call \`report_work_item\`** with \`{ kind: 'source_plan', sessionId, workItemId, leaseId, attempt, sourcePlan: { actions, metadata, executionPlan, bindings? } }\`. Response: \`{ stage: 'awaiting_briefs', briefWorkItem, executionPlan, nextAction: 'report_work_item' }\`.
195
267
 
196
- 4. **Report briefs and start generating — no approval gate.** Call \`report_variant_briefs\` with N briefs; the server starts every direction immediately and returns \`stage: 'work_items_ready'\`. Do NOT pause to ask the user to approve the briefs first. Then call \`continue_variants({ action: 'request_work' })\` and follow Sub-flow A steps 2-5. Work items are \`static_preview\` or \`code_gen\` depending on \`executionPlan.mode\`. On commit, the apply payload is \`payload.kind === 'project-created'\` — the server materialized the chosen variant to \`destinationPath\`.
268
+ 4. **Report briefs and start generating — no approval gate.** Call \`report_work_item(kind='brief')\` with N briefs; the server starts every direction immediately and returns \`stage: 'work_items_ready'\`. Do NOT pause to ask the user to approve the briefs first. Then call \`continue_variants({ action: 'request_work' })\` and follow Sub-flow A steps 2-5. Work items are \`static_preview\` or \`code_gen\` depending on \`executionPlan.mode\`. On commit, the apply payload is \`payload.kind === 'project-created'\` — the server materialized the chosen variant to \`destinationPath\`.
197
269
 
198
270
  ---
199
271
 
@@ -206,14 +278,14 @@ ${describe_motion_protocol_1.DESCRIBE_MOTION_PROTOCOL}
206
278
  - **Never** generate variants natively (${opts.nativeGenLabel}, parallel tool calls, your own creative process) without going through \`start_variants\` first.
207
279
  - **Sequential Varys accumulate — never orphan the earlier batch.** For an existing project, calling \`start_variants\` again while a session is live APPENDS the new directions to that SAME active session, so every batch renders side-by-side in the editor (Rivet keeps one active session per project and never supersedes it). Just call \`start_variants\` per Vary with distinct \`briefs\`; do not pass a prior \`sessionId\` or try to manage accumulation yourself. When a variant-request batch hands you a \`requestId\`, pass it straight through to \`start_variants\` so the editor maps its loading placeholders to the new cards.
208
280
  - Always pass the user's prompt verbatim — don't paraphrase.
209
- - Prefer \`start_variants\` (with the matching \`mode\`) over the older \`propose_variants\` \`report_variant_briefs\` → \`approve_variant_briefs\` chain. The unified call also handles project detection, \`open_visual_editor\`, and \`continue_variants(request_work)\` server-side for kickoff, but it is not a durable watcher. When it returns \`editorNextAction\`, the host agent must keep the \`watch_for_changes\` loop active. The older variant tools and standalone \`open_visual_editor\` stay registered for the Visual Editor flow (point-and-click changes without variants).
281
+ - Prefer \`start_variants\` (with the matching \`mode\`); it replaces the older multi-call kickoff and also handles project detection, \`open_visual_editor\`, and \`continue_variants(request_work)\` server-side for kickoff, but it is not a durable watcher. When it returns \`editorNextAction\`, the host agent must keep the \`watch_for_changes\` loop active. The standalone \`open_visual_editor\` stays registered for the Visual Editor flow (point-and-click changes without variants).
210
282
  - For source-grounded fresh projects, pass the raw references as \`userContext\` to \`start_variants\` and do the design/motion extraction DURING source planning (report \`extract_design_system\` / \`describe_motion\` actions with metadata) — don't pre-summarize references before kickoff.
211
283
  - Briefs are never an approval gate — reporting them starts the directions immediately. Do not pause to ask the user "do these look good?" before generating. If you mention briefs in chat at all they are PLAIN TEXT; do not render UI, open a browser tab, or fabricate a URL.
212
284
  - The user picks AFTER seeing the variants render LIVE in the iframe, not before. Hand off to the iframe chip for visual cycling + commit.
213
285
  - Don't dump diffs in chat by default. The iframe chip is the primary review surface. If the user explicitly asks "show me the diffs", then print them.
214
286
  - Parallel code-gen is the only step where you fan out — every other step is one tool call.
215
- - **Per-variant cancel** is handled by the iframe — the UI calls \`cancel_variant({ sessionId, variantId })\` when the user clicks the cancel button on a card. You do not need to call this from the agent side. Use \`cancel_variants\` (plural) only to kill an entire session.
216
- - **Honor aborts mid-generation.** When the user removes or cancels a direction while it is still generating, the very next \`report_variant_complete\` for that work item returns \`{ aborted: true }\`. Treat that as a hard stop for that one direction: abandon it immediately, do NOT retry or re-report it, and keep going on the rest. For directions that take a while to build, send periodic \`status: 'running'\` heartbeats through \`report_variant_complete\` so an abort is caught early instead of after you have spent the work — a cleared lease surfacing as \`{ aborted: true }\` (rather than an error) is the signal to drop it.
287
+ - **Per-variant cancel** is handled by the iframe — the UI calls \`cancel_variants({ sessionId, variantId })\` when the user clicks the cancel button on a card. You do not need to call this from the agent side. Call \`cancel_variants\` without a \`variantId\` to kill the entire session.
288
+ - **Honor aborts mid-generation.** When the user removes or cancels a direction while it is still generating, the very next \`report_work_item(kind='status')\` for that work item returns \`{ aborted: true }\`. Treat that as a hard stop for that one direction: abandon it immediately, do NOT retry or re-report it, and keep going on the rest. For directions that take a while to build, send periodic \`status: 'running'\` heartbeats through \`report_work_item(kind='status')\` so an abort is caught early instead of after you have spent the work — a cleared lease surfacing as \`{ aborted: true }\` (rather than an error) is the signal to drop it.
217
289
  - Quality bar is mandatory: avoid generic hero-card pages; preserve source depth, realistic workflow detail, and responsive interaction states unless the user explicitly asks for a lighter build. This whole-page bar applies when there is NO \`target\`; when the request targets a specific element/file/route, scope the change to that element and its immediate section instead and leave the rest of the page intact.
218
290
  - **QA re-lease**: an existing-project \`code_gen\` work item re-surfaced by \`request_work\` with \`input.qaRetry\` failed the diff task-fit QA gate — its diff added no styling, components, or structured markup for the requested design. Read the QA notes, regenerate that variant so the diff implements the design, then re-report — at most one retry per variant. After the retry a still-empty diff fails the variant terminally rather than looping.`;
219
291
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shared-variants-protocol.js","sourceRoot":"","sources":["../../../src/utils/skills/shared-variants-protocol.ts"],"names":[],"mappings":";;;AAqEA,oEAwCC;AAMD,8DA2HC;AA9OD,yEAAsE;AAEtE;;;GAGG;AACU,QAAA,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;+KA2BkI,CAAC;AAEhL;;;;GAIG;AACU,QAAA,wBAAwB,GACnC,+FAA+F;IAC/F,+HAA+H;IAC/H,0FAA0F;IAC1F,mHAAmH,CAAC;AAEtH,0DAA0D;AAC7C,QAAA,sBAAsB,GAAG;;;;;;;;2LAQqJ,CAAC;AAE5L;;;;;;;;;;;GAWG;AACH,SAAgB,4BAA4B,CAAC,IAU5C;IACC,OAAO;;;;;;;;KAQJ,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;EAoBvC,IAAI,CAAC,cAAc,EAAE,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,SAAgB,yBAAyB,CAAC,IASzC;IACC,OAAO;;gMAEuL,IAAI,CAAC,cAAc,uJAAuJ,IAAI,CAAC,cAAc;;;;;;;;;;;;;;qaAcwC,gCAAwB;;;;;;;KAOxb,IAAI,CAAC,KAAK;;;;;;;;;;;KAWV,IAAI,CAAC,YAAY;;;;;;;;;;;;;;;;;qaAiB+Y,gCAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2C3b,mDAAwB;;;;;;0CAMgB,IAAI,CAAC,cAAc;;;;;;;;;;;;icAYoY,CAAC;AAClc,CAAC"}
1
+ {"version":3,"file":"shared-variants-protocol.js","sourceRoot":"","sources":["../../../src/utils/skills/shared-variants-protocol.ts"],"names":[],"mappings":";;;AA+IA,oEAwCC;AAMD,8DA2HC;AAxTD,yEAAsE;AAEtE;;;GAGG;AACU,QAAA,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;+KA2BkI,CAAC;AAEhL;;;;GAIG;AACU,QAAA,wBAAwB,GACnC,+FAA+F;IAC/F,+HAA+H;IAC/H,0FAA0F;IAC1F,mHAAmH,CAAC;AAEtH;;;GAGG;AACU,QAAA,cAAc,GAAG;;;;;;;;;2MAS6K,CAAC;AAE5M,0DAA0D;AAC7C,QAAA,sBAAsB,GAAG;;;;;;;;;qYAS+V,CAAC;AAEtY;;;;;;;;;;;GAWG;AACU,QAAA,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mlBA4CiiB,CAAC;AAEplB;;;;;;;;;;;GAWG;AACH,SAAgB,4BAA4B,CAAC,IAU5C;IACC,OAAO;;;;;;;;KAQJ,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;EAoBvC,IAAI,CAAC,cAAc,EAAE,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,SAAgB,yBAAyB,CAAC,IASzC;IACC,OAAO;;gMAEuL,IAAI,CAAC,cAAc,uJAAuJ,IAAI,CAAC,cAAc;;;;;;;;;;;;;;qaAcwC,gCAAwB;;;;;;;KAOxb,IAAI,CAAC,KAAK;;;;;;;;;;;KAWV,IAAI,CAAC,YAAY;;;;;;;;;;;;;;;;;qaAiB+Y,gCAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2C3b,mDAAwB;;;;;;0CAMgB,IAAI,CAAC,cAAc;;;;;;;;;;;;icAYoY,CAAC;AAClc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rivet-design",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "description": "Local visual web development tool with AI-powered code modification",
5
5
  "main": "dist/index.js",
6
6
  "workspaces": [
@@ -55,54 +55,18 @@
55
55
  "@anthropic-ai/claude-agent-sdk": "^0.1.42",
56
56
  "@contextcompany/claude": "^1.0.0",
57
57
  "@modelcontextprotocol/sdk": "1.27.1",
58
- "@phosphor-icons/react": "^2.1.10",
59
- "@radix-ui/react-accordion": "^1.2.11",
60
- "@radix-ui/react-popover": "^1.1.15",
61
- "@radix-ui/react-select": "^2.2.6",
62
- "@radix-ui/react-tabs": "^1.1.13",
63
- "@radix-ui/react-toast": "^1.2.14",
64
- "@radix-ui/react-tooltip": "^1.2.8",
65
- "@react-aria/color": "^3.1.2",
66
- "@react-aria/focus": "^3.21.2",
67
- "@react-aria/i18n": "^3.12.13",
68
- "@react-stately/color": "^3.9.2",
69
58
  "@sentry/node": "10.44.0",
70
- "@types/cors": "^2.8.19",
71
- "@types/express": "^5.0.3",
72
- "@types/node": "^25.4.0",
73
- "@types/react": "^18.2.43",
74
- "@types/react-dom": "^18.2.17",
75
- "@vitejs/plugin-react": "^4.2.1",
76
- "autoprefixer": "^10.4.16",
77
- "bippy": "^0.5.8",
78
- "chroma-js": "^3.2.0",
79
- "class-variance-authority": "^0.7.1",
80
- "clsx": "^2.1.1",
81
59
  "cors": "^2.8.5",
82
60
  "dotenv": "^17.4.2",
83
61
  "express": "^5.2.1",
84
62
  "glob": "^11.0.3",
85
63
  "http-proxy-middleware": "^3.0.5",
86
- "jotai": "^2.13.1",
87
64
  "loglevel": "^1.9.2",
88
- "lottie-react": "^2.4.1",
89
- "motion": "^12.23.12",
90
65
  "open": "^8.4.0",
91
- "postcss": "^8.4.32",
92
- "posthog-js": "^1.264.2",
93
66
  "posthog-node": "^5.28.1",
94
- "react": "^18.2.0",
95
- "react-dom": "^18.2.0",
96
67
  "redis": "^5.12.1",
97
68
  "simple-git": "^3.19.1",
98
- "sonner": "^2.0.7",
99
- "tailwind-merge": "^3.3.1",
100
- "tailwindcss": "^3.4.0",
101
- "ts-api-utils": "^2.4.0",
102
69
  "typescript": "^5.1.6",
103
- "uuid": "^14.0.0",
104
- "vite": "^6.4.2",
105
- "ws": "^8.18.3",
106
70
  "zod": "^3.24.1"
107
71
  },
108
72
  "devDependencies": {
@@ -112,13 +76,20 @@
112
76
  "@testing-library/jest-dom": "^6.9.1",
113
77
  "@testing-library/react": "^16.3.0",
114
78
  "@types/chroma-js": "^3.1.2",
79
+ "@types/cors": "^2.8.19",
80
+ "@types/express": "^5.0.3",
115
81
  "@types/jest": "^30.0.0",
116
82
  "@types/js-yaml": "^4.0.9",
83
+ "@types/node": "^25.4.0",
84
+ "@types/react": "^18.2.43",
85
+ "@types/react-dom": "^18.2.17",
117
86
  "@types/supertest": "^6.0.3",
118
87
  "@types/uuid": "^11.0.0",
119
88
  "@types/ws": "^8.18.1",
120
89
  "@typescript-eslint/eslint-plugin": "^8.44.0",
121
90
  "@typescript-eslint/parser": "^8.44.0",
91
+ "@vitejs/plugin-react": "^4.2.1",
92
+ "autoprefixer": "^10.4.16",
122
93
  "eslint": "^9.36.0",
123
94
  "eslint-config-prettier": "^10.1.8",
124
95
  "eslint-plugin-react": "^7.37.5",
@@ -132,13 +103,20 @@
132
103
  "lint-staged": "^16.1.6",
133
104
  "playwright": "^1.58.2",
134
105
  "playwright-core": "^1.58.2",
106
+ "postcss": "^8.4.32",
135
107
  "prettier": "^3.6.2",
136
108
  "prettier-plugin-tailwindcss": "^0.7.2",
109
+ "react": "^18.2.0",
110
+ "react-dom": "^18.2.0",
137
111
  "supabase": "^2.47.2",
138
112
  "supertest": "^7.1.4",
113
+ "tailwindcss": "^3.4.0",
114
+ "ts-api-utils": "^2.4.0",
139
115
  "ts-jest": "^29.4.4",
140
116
  "ts-node": "^10.9.2",
141
- "tsx": "^4.21.0"
117
+ "tsx": "^4.21.0",
118
+ "vite": "^6.4.2",
119
+ "ws": "^8.18.3"
142
120
  },
143
121
  "files": [
144
122
  "dist/",