@marver-design/marver 0.16.1 → 0.17.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.
package/docs/live-jam.md CHANGED
@@ -89,19 +89,31 @@ resolves a thread; you do that after reviewing.
89
89
 
90
90
  The missing sense that no-shell used to cost - "does my frame actually RENDER?" - is a
91
91
  server capability instead, rendered in the machine's own headless Chrome (no bundled
92
- browser, CDP over Node's built-in WebSocket) and written as a PNG under
92
+ browser; CDP over Chrome's debugging pipe, so the browser lives exactly as long as the
93
+ shot) and written as a PNG under
93
94
  `design/.local/shots/`. Two transports reach it, because the no-shell jail rules out the
94
95
  obvious one:
95
96
 
96
97
  - **The file-drop inbox** (works for every agent, including Claude Code, which has no shell
97
98
  and whose WebFetch refuses localhost). The agent writes
98
- `design/.local/shots/<slug>.request.json` with `{"frame":"<id>","theme":"<t>"}`; the dev
99
- server renders and writes `<slug>.result.json` with the PNG path or an error, which the
100
- agent Reads.
101
- - **`npx marver shot <frame> [--scale 1-4]`** / `GET /api/shot?frame=<id>&theme=<t>&scale=<n>`
102
- for humans and shell-ful agents - the same renderer, one line. Default 2x; `--scale 4` for a
103
- print-quality still (a slide comes back 5120×2880). A frame too tall for the asked scale steps
104
- down and says so in `note`; the file name carries the scale actually used (`…@4x.png`).
99
+ `design/.local/shots/<slug>.request.json` with `{"frame":"<id>","theme":"<t>"}` - or
100
+ `{"scene":"<name>"}`, `{"frames":[...]}`, `{"all":true}` for a batch; the dev server renders
101
+ and writes `<slug>.result.json` with the PNG path or an error (a batch: `results`, one entry
102
+ per frame), which the agent Reads.
103
+ - **`npx marver shot <frame ...> | --scene <name> | --all [--scale 1-4] [--json]`** /
104
+ `GET /api/shot?frame=<id>&theme=<t>&scale=<n>` / `POST /api/shots {frames|scene|all, theme,
105
+ scale}` for humans and shell-ful agents - the same renderer, one line. A batch is ONE
106
+ operation: one headless browser, `MARVER_SHOT_CONCURRENCY` frames at a time inside it
107
+ (default up to 6, sized to the machine), so a scene costs about what a frame does. Default
108
+ 2x; `--scale 4` for a print-quality still (a slide comes back 5120×2880). A frame too tall
109
+ for the asked scale steps down and says so in `note`; the file name carries the scale
110
+ actually used (`…@4x.png`). A frame that ran out of settle budget still ships, marked
111
+ `unsettled` with a note.
112
+ - **The browser's life.** The headless Chrome exists only while an operation runs - it is
113
+ driven over Chrome's own debugging pipe, so it dies with the dev server however the server
114
+ dies (Ctrl-C, a closed terminal, `kill -9`), and none is kept between shots. `MARVER_CHROME`
115
+ picks the binary; pointing it at a Chrome for Testing or Chromium build makes the shot
116
+ browser a different app from your own, which some people prefer on macOS.
105
117
  The canvas's **copy as image** (`i` / `⇧i`, the images-square toolbar button) is this same
106
118
  renderer with `format=png`, so what a designer pastes and what an agent shoots is one picture.
107
119
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marver-design/marver",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "description": "The agent-native design canvas. A design/ folder, one command, a canvas of live frames built from your repo's real components - comment @marver and your own coding agent does the work. The tool ships no AI.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -81,7 +81,10 @@ planning. The human should see the request land on the canvas within the first m
81
81
  lit frame, never before one.
82
82
  3. Build. Independent frames can go in parallel - one subagent per frame, each marking
83
83
  its own; frames that depend on one another go in order.
84
- 4. **Clear as you finish**: `npx marver work done <scene/frame ...>` (or `--all`). Marks
84
+ 4. **Look before you say done**: `npx marver shot --scene <scene>` (or `<scene/frame ...>`,
85
+ `--all`) renders the frames headless in one go - one PNG path per line - and you READ
86
+ the PNGs. No shell? instructions/jam.md has the file-drop way (`{"scene":"..."}`).
87
+ 5. **Clear as you finish**: `npx marver work done <scene/frame ...>` (or `--all`). Marks
85
88
  self-expire (default 10 min; `--ttl <min>` up to 30) - re-run `start` on long jobs,
86
89
  and never lean on expiry instead of `done`.
87
90
 
@@ -81,7 +81,10 @@ planning. The human should see the request land on the canvas within the first m
81
81
  lit frame, never before one.
82
82
  3. Build. Independent frames can go in parallel - one subagent per frame, each marking
83
83
  its own; frames that depend on one another go in order.
84
- 4. **Clear as you finish**: `npx marver work done <scene/frame ...>` (or `--all`). Marks
84
+ 4. **Look before you say done**: `npx marver shot --scene <scene>` (or `<scene/frame ...>`,
85
+ `--all`) renders the frames headless in one go - one PNG path per line - and you READ
86
+ the PNGs. No shell? instructions/jam.md has the file-drop way (`{"scene":"..."}`).
87
+ 5. **Clear as you finish**: `npx marver work done <scene/frame ...>` (or `--all`). Marks
85
88
  self-expire (default 10 min; `--ttl <min>` up to 30) - re-run `start` on long jobs,
86
89
  and never lean on expiry instead of `done`.
87
90
 
@@ -98,6 +98,15 @@ file - the dev server renders it and writes the PNG back:
98
98
  3. **Read the PNG** at that `path` and check it with your own eyes: content present, both
99
99
  themes if you touched theming, nothing clipped. Fix and re-shoot; files overwrite in place.
100
100
 
101
+ **Several frames? Ask for them in ONE request** - a whole scene renders in one browser,
102
+ several frames at a time, for about the cost of one shot. Write any `<name>.request.json`
103
+ with `{"scene":"checkout"}`, or `{"frames":["checkout/cart","checkout/summary"]}`, or
104
+ `{"all":true}` (plus `"theme"`, `"scale"` as you like). The result is
105
+ `{"ok":true,"results":[{"frame":"checkout/cart","ok":true,"path":"..."},...]}`, one entry
106
+ per frame in the order asked; a frame that failed carries its own `"ok":false,"error"` and
107
+ the others still ship. A frame that ran out of time to settle (a slow image, a heavy chart)
108
+ comes back with `"unsettled":true` and a `note` - shoot that one alone before you judge it.
109
+
101
110
  The `result.json` is the universal signal - it works even when you cannot see images.
102
111
  `"ok":false` means the frame did not render: the `error` carries the reason (a runtime
103
112
  throw shows the frame's own exception, "the frame rendered an error - ..."; an unreachable
@@ -108,9 +117,12 @@ shot at its natural width and its FULL height, so a wide layout or a long spec r
108
117
  full, not cropped. A frame tall enough to hit the capture cap comes back with
109
118
  `"truncated":true` and a `note` - split it or shorten it and re-shoot.
110
119
 
111
- (If you DO have a shell - `npx marver shot <scene/frame> [--theme dark] [--scale 4]` is the
112
- same thing in one line, printing the PNG path. `--scale 4` is for a print-quality still - the
113
- human's "copy as image" on the canvas uses this same renderer, so you both see one picture.)
120
+ (If you DO have a shell - `npx marver shot <scene/frame ...>`, `npx marver shot --scene
121
+ <name>` or `--all` (`[--theme dark] [--scale 4] [--json]`) is the same thing in one line,
122
+ printing one PNG path per line; a failed frame goes to stderr and the exit code is 1. After
123
+ writing a scene, shoot the scene, not the frames. `--scale 4` is for a print-quality still -
124
+ the human's "copy as image" on the canvas uses this same renderer, so you both see one
125
+ picture.)
114
126
 
115
127
  Verification is best-effort, not a gate. If your model cannot read images, or the result
116
128
  reports no Chrome on the machine, still act on `ok`/`error` - and say plainly in your reply
@@ -183,7 +183,8 @@ of described imagery every time (the full asset rules: instructions/craft.md,
183
183
  never set a frame height - the frame auto-heights to fit everything the canvas
184
184
  measures. Marver renders images crisp and zooms fast, so fine detail is one zoom away.
185
185
  - Judge on the RENDER, not the props: after composing, look at the actual frame
186
- (screenshot it if you can) and adjust the per-row count until it reads well. "The code
186
+ (`npx marver shot --scene <scene>` shoots the whole scene in one go; instructions/jam.md
187
+ has the shell-less way) and adjust the per-row count until it reads well. "The code
187
188
  says they're the same width" proves nothing.
188
189
 
189
190
  ## When Shape ends
@@ -1,30 +0,0 @@
1
- import { n as NAME } from "./cli.mjs";
2
- import { readDevInfo } from "./work-CLrmY-vQ.mjs";
3
- //#region src/cli/shot.ts
4
- /**
5
- * `marver shot <scene/frame>` - render one frame headless and print the PNG path.
6
- *
7
- * The shell-ful agents' door into the same verify loop jam teaches: build, shoot, LOOK.
8
- * Thin wrapper over the dev server's /api/shot (shot.ts has the capture story).
9
- */
10
- async function shotCommand(root, frame, opts) {
11
- if (!frame) throw new Error(`name the frame: ${NAME} shot <scene/frame> [--theme <name>] [--scale 1-4]`);
12
- const info = readDevInfo(root);
13
- if (!info) throw new Error(`\`${NAME} dev\` is not running in this repo (design/.local/dev.json not found) - start it first.`);
14
- const qs = new URLSearchParams({
15
- frame,
16
- ...opts.theme ? { theme: opts.theme } : {},
17
- ...opts.scale != null ? { scale: String(opts.scale) } : {}
18
- });
19
- let res;
20
- try {
21
- res = await fetch(`http://localhost:${info.port}/__mv/api/shot?${qs}`, { headers: { "x-mv-work": info.token } });
22
- } catch {
23
- throw new Error(`could not reach \`${NAME} dev\` on port ${info.port} - is it still running?`);
24
- }
25
- const data = await res.json().catch(() => ({}));
26
- if (!res.ok || !data.path) throw new Error(data.error ?? `shot failed (${res.status})`);
27
- console.log(data.path);
28
- }
29
- //#endregion
30
- export { shotCommand };