@field/cascade 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/AGENTS.md +17 -1
  2. package/CHANGELOG.md +214 -0
  3. package/DESIGN.md +14 -0
  4. package/README.md +41 -25
  5. package/dist/assets/CodeEditor-DSZBpzdy.js +623 -0
  6. package/dist/assets/CodePanel-sY6sZa7B.js +2 -0
  7. package/dist/assets/{CustomNodeDialog-BQbEhIwL.js → CustomNodeDialog-BRKnqZhp.js} +1 -1
  8. package/dist/assets/{ExportDialog-CjTbbTZJ.js → ExportDialog-C7dVGua4.js} +2 -2
  9. package/dist/assets/OpenGraphDialog-ZsgL-iwr.js +1 -0
  10. package/dist/assets/ProjectSettings-Cw17nNe3.js +2 -0
  11. package/dist/assets/SettingsDialog-p25h3tj0.js +1 -0
  12. package/dist/assets/{VersionHistoryDialog-D6VBzSQ0.js → VersionHistoryDialog-DzFLUotB.js} +2 -2
  13. package/dist/assets/{core-BInLG4gw.js → core-BICrEt0y.js} +8 -8
  14. package/dist/assets/{cssMode-DfR2qmYG.js → cssMode-D7TXw57I.js} +1 -1
  15. package/dist/assets/definitions-DUww2Rt-.js +1 -0
  16. package/dist/assets/{editor.api-Ck8_vgQV.js → editor.api-DvkCO3ko.js} +1 -1
  17. package/dist/assets/{freemarker2-fVn10Wn3.js → freemarker2-BA2lxsF1.js} +1 -1
  18. package/dist/assets/geo-C2RHOVHC.js +1 -0
  19. package/dist/assets/{handlebars-BCSchLT2.js → handlebars-BcDiyPd8.js} +1 -1
  20. package/dist/assets/{html-CVpSv_k9.js → html-C7O4TyhX.js} +1 -1
  21. package/dist/assets/{htmlMode-Da4ESTv0.js → htmlMode-WaDGF3Mj.js} +1 -1
  22. package/dist/assets/{image-BLn--oSF.js → image-DR4oeyJB.js} +3 -3
  23. package/dist/assets/index-7vae6YFC.css +1 -0
  24. package/dist/assets/index-DyvDC6pS.js +219 -0
  25. package/dist/assets/index-client-DqYmKstU.js +1 -0
  26. package/dist/assets/{javascript-BpX0Gvcf.js → javascript-CpIEK7tz.js} +1 -1
  27. package/dist/assets/{jsonMode-CsLqaou7.js → jsonMode-B2FltW0f.js} +1 -1
  28. package/dist/assets/legacy-CTEeXeqF.js +2 -0
  29. package/dist/assets/{liquid-efUz51Wf.js → liquid-CN6FFHZE.js} +1 -1
  30. package/dist/assets/{lspLanguageFeatures-DCi5-K0n.js → lspLanguageFeatures-QhV9XtLp.js} +1 -1
  31. package/dist/assets/math-DaDEgWKt.js +1 -0
  32. package/dist/assets/{mdx-DP_sjGVy.js → mdx-DE89pafV.js} +1 -1
  33. package/dist/assets/pop-pLH7L0PW.js +1 -0
  34. package/dist/assets/{python-aAuP3LUi.js → python-ByTllTB9.js} +1 -1
  35. package/dist/assets/{razor-7M6sMmC5.js → razor-USYlRRCE.js} +1 -1
  36. package/dist/assets/studioScenes-8sq9FfFg.js +1 -0
  37. package/dist/assets/{tsMode-Bf4CnoYK.js → tsMode-BXpN8iUz.js} +1 -1
  38. package/dist/assets/{typescript-ddhYBGyT.js → typescript-DInBjGQQ.js} +1 -1
  39. package/dist/assets/{workers-X5la8DDT.js → workers-C7Ye5B7D.js} +1 -1
  40. package/dist/assets/{xml-BzbXa3Ps.js → xml-U0Uocqyo.js} +1 -1
  41. package/dist/assets/{yaml-CXs-VzxL.js → yaml-CBw_PVYf.js} +1 -1
  42. package/dist/cli/index.js +19978 -3423
  43. package/dist/cli/runtime/stage.ts +70 -10
  44. package/dist/contracts/bundle.d.ts +75 -0
  45. package/dist/contracts/bundle.js +112 -0
  46. package/dist/contracts/definition.d.ts +67 -4
  47. package/dist/contracts/document.d.ts +29 -0
  48. package/dist/contracts/editor.d.ts +172 -0
  49. package/dist/contracts/editor.js +2 -0
  50. package/dist/contracts/index.d.ts +2 -0
  51. package/dist/contracts/index.js +2 -0
  52. package/dist/contracts/validate.js +59 -3
  53. package/dist/contracts/values.d.ts +3 -3
  54. package/dist/contracts/values.js +1 -0
  55. package/dist/index.html +4 -4
  56. package/dist/player/app.js +17 -5
  57. package/dist/player/editor.js +1894 -0
  58. package/dist/player/editorEngine.js +477 -0
  59. package/dist/runtime/builtins/core/bundle.d.ts +70 -0
  60. package/dist/runtime/builtins/core/bundle.js +81 -0
  61. package/dist/runtime/builtins/core/index.d.ts +3 -2
  62. package/dist/runtime/builtins/core/index.js +6 -2
  63. package/dist/runtime/builtins/core/routing.d.ts +27 -0
  64. package/dist/runtime/builtins/core/routing.js +28 -0
  65. package/dist/runtime/edit/document.d.ts +94 -0
  66. package/dist/runtime/edit/document.js +194 -0
  67. package/dist/runtime/edit/graphEditor.d.ts +223 -0
  68. package/dist/runtime/edit/graphEditor.js +893 -0
  69. package/dist/runtime/edit/index.d.ts +12 -0
  70. package/dist/runtime/edit/index.js +6 -0
  71. package/dist/runtime/edit/layout.d.ts +50 -0
  72. package/dist/runtime/edit/layout.js +126 -0
  73. package/dist/runtime/edit/operations.d.ts +65 -0
  74. package/dist/runtime/edit/operations.js +57 -0
  75. package/dist/runtime/edit/parameters.d.ts +75 -0
  76. package/dist/runtime/edit/parameters.js +284 -0
  77. package/dist/runtime/edit/read.d.ts +35 -0
  78. package/dist/runtime/edit/read.js +65 -0
  79. package/dist/runtime/editor/index.d.ts +104 -0
  80. package/dist/runtime/editor/index.js +439 -0
  81. package/dist/runtime/expressions/bundlePaths.d.ts +37 -0
  82. package/dist/runtime/expressions/bundlePaths.js +55 -0
  83. package/dist/runtime/expressions/index.d.ts +2 -0
  84. package/dist/runtime/expressions/index.js +1 -0
  85. package/dist/runtime/index.d.ts +2 -0
  86. package/dist/runtime/index.js +2 -0
  87. package/dist/runtime/params/animator.d.ts +5 -0
  88. package/dist/runtime/params/animator.js +16 -0
  89. package/dist/runtime/runtime.js +238 -12
  90. package/dist/runtime/seed.d.ts +29 -0
  91. package/dist/runtime/seed.js +52 -0
  92. package/dist/runtime/types.d.ts +12 -0
  93. package/dist/stage.js +40 -9
  94. package/dist/studio/panel.d.ts +2 -0
  95. package/doc/CLI_REFERENCE.md +100 -0
  96. package/doc/EDITOR_EXPORT.md +226 -0
  97. package/doc/HEADLESS_GPU.md +27 -0
  98. package/doc/MCP.md +53 -0
  99. package/doc/NODE_REFERENCE.md +66 -0
  100. package/doc/PROJECT_AUTHORING.md +137 -0
  101. package/package.json +15 -6
  102. package/dist/assets/CodeEditor-BEk-kIBd.js +0 -623
  103. package/dist/assets/CodePanel-CeSdjXkg.js +0 -2
  104. package/dist/assets/OpenGraphDialog-DCwH9itM.js +0 -1
  105. package/dist/assets/ProjectSettings-Dg7M5xt9.js +0 -2
  106. package/dist/assets/SettingsDialog-e7GgsjB9.js +0 -1
  107. package/dist/assets/definitions-DZpOjWKR.js +0 -1
  108. package/dist/assets/geo-D2VPjAdt.js +0 -1
  109. package/dist/assets/index-CMiBdEuT.js +0 -212
  110. package/dist/assets/index-DMIuml9a.css +0 -1
  111. package/dist/assets/index-client-BI2H82FJ.js +0 -1
  112. package/dist/assets/legacy-ZA7textG.js +0 -2
  113. package/dist/assets/math-B6hpxPJO.js +0 -1
  114. package/dist/assets/pop-CYUIjT6x.js +0 -1
  115. package/dist/assets/projectSettingsApi-C1WvIwfP.js +0 -1
package/AGENTS.md CHANGED
@@ -37,11 +37,19 @@ my-project/
37
37
 
38
38
  Use `cascade new <name>` to create a project and `cascade node <Name>` to scaffold a custom node in one. Run `cascade .` from a project root to open Studio, `cascade validate <graph.cascade>` for validation, `cascade check <graph.cascade>` for static definition/type checks, `cascade inspect <graph.cascade>` for a JSON summary, `cascade run <graph.cascade>` for headless execution, and `cascade run <graph.cascade> --frames 1-100` for an offline image sequence. `cascade projects` shows or sets the default projects directory.
39
39
 
40
+ Never hand-edit a `.cascade` file. Change graphs with `cascade node add|rm`, `connect`, `disconnect`, `set` and `subnet create|move|dissolve` (or `cascade edit` for a batch); they check the edit like `cascade check`, keep the diff minimal and lay new nodes out. Every command takes `--json`, and `cascade mcp` serves the same operations as MCP tools. Read `doc/CLI_REFERENCE.md` and `doc/MCP.md`.
41
+
40
42
  `cascade build <graph.cascade> --out <new-directory>` exports a static browser
41
43
  player. Use repeatable `--asset <project-relative-file>` for inputs whose paths
42
44
  are computed in code. Read `doc/WEB_PLAYER.md` before exporting: server stages
43
45
  and dynamic modules are not supported, assets must be explicit, and an existing
44
46
  output directory is never overwritten. Serve the result over HTTP, not file://.
47
+ `cascade export <graph.cascade> (--plan | --out <dir>)` exports the graph's
48
+ `editor` section (published parameters, outputs, presets) as a shareable static
49
+ editor. Read `doc/EDITOR_EXPORT.md` first. The export is an allowlist: live
50
+ sources must be frozen (`cascade freeze`), and `licensed/`, hidden and
51
+ gitignored files are refused. Scenes round-trip through the editor, Studio and
52
+ `cascade run --scene`.
45
53
  The player is an application host under `src/player`, not another graph engine.
46
54
  Each embed owns an iframe realm, assets, IO bridge and GPU lifecycle. No Studio
47
55
  imports or `/api/*` dependency may enter the static deployment.
@@ -71,6 +79,14 @@ curl -fsS http://KURO:3030/health
71
79
  curl -fsS http://KURO:3030/api/graph
72
80
  ```
73
81
 
82
+ For a Studio that should stay up, use `cascade serve` instead of a `screen`:
83
+ `cascade serve start <project> --host KURO --port 3030`, then
84
+ `cascade serve status [project] --json`, `logs`, `restart` and `stop`. It keeps
85
+ one supervisor per project, restarts a crashed Studio, and stops the Python
86
+ worker with it. If the host is unavailable (Tailscale down) Studio binds
87
+ `127.0.0.1` and moves back when the host returns; `status` shows the actual
88
+ binding. Never stop or restart a served Studio you did not start.
89
+
74
90
  Remote access is explicit: a specific non-loopback `--host` is also the default
75
91
  trusted browser hostname. Use `--trusted-host` only when the bind address and
76
92
  browser hostname differ. Hostnames are exact and case-insensitive; wildcard
@@ -212,7 +228,7 @@ the TypeScript 7 preview until it is stable and the repository gates pass.
212
228
  1. Add or update a focused regression test.
213
229
  2. Make the smallest change at the owning layer.
214
230
  3. Prefer deletion or an existing utility over another wrapper.
215
- 4. Run the focused test, then `npm run check`, `npm run test:run`, `npm --prefix server run build`, `npm run build`, and `npm run build:cli` when the affected surface warrants it. Keep the CLI build last because Vite refreshes `dist/`.
231
+ 4. Run the focused test, then `npm run check`, `npm run test:run`, `npm --prefix server run build`, `npm run build`, and `npm run build:cli` when the affected surface warrants it. Both builds write to a staging directory and replace `dist/` only on success, so a failed build leaves the previous CLI working.
216
232
  5. For package/public API changes, also test the packed tarball from an empty temporary project.
217
233
  6. When a built-in definition or a node library registry changes, regenerate the node reference with `npm run build:node-reference` and commit the result. `build:cli` runs it too, so a full build will produce the diff whether or not you meant to. Nothing tests that the committed file is current, so a stale one ships silently — and it is the first thing a project's agent reads.
218
234
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,220 @@
2
2
 
3
3
  Notable changes to Cascade. Newest first.
4
4
 
5
+ ## 0.10.0 — 2026-10-12
6
+
7
+ ### Added
8
+
9
+ - **The timeline is saved with the graph.** `timeline: { fps, start, end,
10
+ loop }` in the document: Studio's Timeline opens on it and writes it back,
11
+ the runtime uses its fps, and `cascade run --frames timeline` renders its
12
+ range.
13
+ - **`run --frames … --mp4 <file> [--crf N]`** encodes the rendered sequence
14
+ with ffmpeg as H.264 yuv420p at the run's fps, and reports it as `video` in
15
+ the `--json` manifest.
16
+ - **Stage cache keys Cascade owns.** Every Python stage call, Studio or
17
+ headless, is keyed on the stage code (a hash of `exec.stages.sources`), the
18
+ arguments with input files replaced by their content hash, and the Cascade
19
+ version, and its cache state (`hit`, `miss`, `off`) and key are reported on
20
+ every call: in the server log, in `run --json` under `stages`, and in the run
21
+ trace. `exec.stages.cache` turns on a core result cache that verifies the
22
+ files a stored result names before serving it.
23
+ - **Run traces.** Every `cascade run` writes `.cascade/runs/<time>-<graph>.json`
24
+ with each node's time and its stage calls. `run --json` works without
25
+ `--frames`.
26
+ - **Seeds.** `context.seed` (from the document's `seed` and the node id) and
27
+ `context.random()` in both hosts; `cascade run --seed N`.
28
+ - **`cascade parity <graph> [--node] [--tolerance] [--json]`** cooks headless
29
+ twice and through Studio's executor with caches off and reports every node
30
+ output side by side.
31
+ - **Locks and replay.** `cascade lock <graph> <node> --name <name>` records one
32
+ render in `locks/<id>.json`: the graph as cooked, every prop and seed, input
33
+ file hashes, the project's source code (stored by hash in
34
+ `.cascade/objects/`), versions and git state, and a fingerprint of every
35
+ output. `cascade replay <id>` rebuilds that code in a throwaway copy of the
36
+ project and compares fingerprints, without a worktree; `--live` uses the
37
+ current code instead. `cascade lock verify` replays every lock and
38
+ `cascade locks` lists them. All take `--json`.
39
+
40
+ - **`cascade serve`.** `start | stop | restart | status | logs | install |
41
+ uninstall [project]` runs Studio as a supervised background service: one
42
+ lock, record and log per project under `~/.cascade/serve/`, restart with
43
+ backoff after a crash, and a stop that takes the Python worker with it.
44
+ `status --json` reports port, actual host, pids, uptime, version and worker
45
+ state. `install` writes and loads a macOS launchd job.
46
+ - **Host fallback.** When `--host` does not resolve (a MagicDNS name while
47
+ Tailscale is down) or is not on this machine (`EADDRNOTAVAIL`), Studio binds
48
+ `127.0.0.1` (or `--fallback-host`, repeatable) instead of crashing, and moves
49
+ back to the preferred host when it returns.
50
+ - **Graph editing from the CLI.** `cascade graph create|read|list`, `node add|rm`, `connect`, `disconnect`, `set` (value, `--expr`, `--key frame=value`, `--unset`), `subnet create|move|dissolve` and `cascade edit` for a batch. Each edit is checked with the same code as `cascade check`, written atomically in the file's own formatting, and leaves a minimal diff: an edit and its inverse leave the file byte-identical. New nodes get stable kebab-case ids and are placed along the graph's flow when wired; wires across a subnet boundary go through named `Input`/`Output` nodes. See `doc/CLI_REFERENCE.md`.
51
+ - **`--json` on every command**: one `{ ok, data, warnings }` envelope on stdout.
52
+ - **`cascade mcp`**: the same operations as MCP tools over stdio (graph read/list, node add/remove, connect, set, subnets, check, cook, render, export; lock and replay once they land). See `doc/MCP.md`.
53
+ - The editing API (`GraphEditor`, `readGraph`, the operation types) is exported from `@field/cascade/runtime`.
54
+
55
+ ### Changed
56
+
57
+ - `cascade run --frames --json` prints its manifest inside the envelope, as `data`, rather than at the top level.
58
+
59
+ ### Fixed
60
+
61
+ - **Headless frame renders no longer start Python per stage per frame.**
62
+ `cascade run` uses the project's warm worker for the whole run, and frames
63
+ after the first re-cook only what the frame changed (`reuse: "strict"`;
64
+ `--fresh` cooks everything). cloud-plots' morph, frames 1–60: 588 s to 5 s,
65
+ byte-identical.
66
+
67
+ - **An edited stage no longer runs its old code in a live Studio.** The warm
68
+ Python worker restarts before the next request when its stage sources
69
+ change, with Python's bytecode cache keyed by the code hash so a quick
70
+ same-length edit is not served from an old `.pyc`.
71
+
72
+ - **A failed build keeps the previous `dist/`.** `npm run build` and
73
+ `build:cli` build into `.dist-staging/` and swap it in only when every step
74
+ passed; the log names the step that failed.
75
+
76
+ ## 0.9.2 — 2026-10-12
77
+
78
+ ### Added
79
+
80
+ - **Exported editors work on phones.** The preview is full width at the top,
81
+ with pinch, pan and double-tap to fit. Controls sit in a bottom sheet with
82
+ three snap points and folded groups, sized for thumbs (44 px targets, 16 px
83
+ text, steppers). The header is one row with a ⋯ menu. Safe-area insets and
84
+ `100dvh` keep everything clear of Safari's toolbar. Exports and scenes use the
85
+ share sheet, with a download as the fallback. Landscape uses a side panel, and
86
+ desktop is unchanged.
87
+ - **`editor.peek` and `editor.draft`.** These choose the controls kept in reach
88
+ at the sheet's lowest point, and the values cooked while a slider is dragged
89
+ (a lower density, say).
90
+
91
+ ## 0.9.1 — 2026-10-11
92
+
93
+ ### Added
94
+
95
+ - **Share from the Inspector.** Studio's Inspector has a `share` toggle per
96
+ parameter that publishes it to the exported editor, with label, group and
97
+ min/max/step fields.
98
+
99
+ ### Changed
100
+
101
+ - **The exported editor cooks in a module worker** (`editor-worker.js`), so a
102
+ slow stage no longer freezes the page while someone drags a slider.
103
+
104
+ ### Fixed
105
+
106
+ - **A fresh tree builds.** `npm run build` compiles the workspace packages
107
+ before vite, and no longer leaves `dist/` without a CLI.
108
+
109
+ ## 0.9.0 — 2026-10-11
110
+
111
+ ### Added
112
+
113
+ - **Shareable editors (0.9.0).** `cascade export <graph> --out <dir>` builds a
114
+ static editor site from a graph's new `editor` section. It has the published
115
+ parameters (with a UI generated from their types), presets, scene files, one
116
+ export button per declared output, and a read-only inspect view of every
117
+ stage. `--plan` prints the manifest without building, and
118
+ `--deploy vercel` deploys the site and checks that Vercel Authentication is
119
+ on.
120
+
121
+ The export is an allowlist. It ships the subgraph the outputs need and the
122
+ selected assets, and nothing else. It refuses Python and dynamic nodes,
123
+ wired-in live sources, `licensed/`, hidden and gitignored files. It scans the
124
+ built site for credentials, local paths and backend URLs.
125
+ `cascade freeze` snapshots chosen fields of a live source, and
126
+ `cascade publish` marks a prop as a parameter. Scenes (`*.scene.json`) open
127
+ in the editor, in Studio (File › Open/Save Scene) and in the CLI
128
+ (`cascade scene`, `cascade run --scene --write`), with versioned,
129
+ degrade-gracefully matching.
130
+
131
+ The runtime gains `run({ reuse: true })`, an early cutoff for hosts that
132
+ re-run on every edit, and `cascade.core.Frozen`. Node definitions gain
133
+ `source: "live"`. See `doc/EDITOR_EXPORT.md`.
134
+
135
+ - **Bundle ports.** A node can export one `bundle` port carrying named fields
136
+ instead of a dozen loose outputs. A producer declares `fields` (name to type)
137
+ and an optional `schema`; a consumer declares the `fields` it reads, sees only
138
+ those, and in Studio re-cooks only when one of them changed (per-field
139
+ versions on top of early cutoff). Expressions read a wired bundle's fields
140
+ with `ch("format.dpi")`. `cascade.core.Pick` and `cascade.core.Pack` convert
141
+ between bundles and single values. `cascade check` reports unknown fields with
142
+ the nearest declared name, and refuses an absolute read of another node's
143
+ bundle. Studio draws a bundle as one neutral port whose hover and Inspector
144
+ list its fields and values. Bundles reach Python stages as dicts. See
145
+ "Bundle ports" in `doc/PROJECT_AUTHORING.md`.
146
+
147
+ - **Node previews on the canvas.** A project that sets
148
+ `settings.nodePreviews: true` in `cascade.json` shows each node's first
149
+ output as a readable preview card on the graph, refreshed per node cook. The
150
+ same settings can carry a `workspace` used as the first-open dock layout when
151
+ the browser has none saved; a layout that fails to load falls back to the
152
+ built-in one.
153
+
154
+ - **Groups own their contents.** A group frame keeps an explicit
155
+ `containedElements` list, separate from subnet parenting. Drag the frame
156
+ header to move its members (nested contents move once); drop an item's
157
+ centre inside a frame to add it, outside to remove it, and the smallest
158
+ enclosing frame wins. The target frame highlights before release, and
159
+ membership and positions share one undo step. Deleting a frame leaves its
160
+ contents. View → Clean Up Layout now treats each group as a cluster: it lays
161
+ out members first, fits the frame, then places the groups.
162
+
163
+ - **The Agent console keeps a Codex conversation, and panels can hand it a
164
+ draft.** A Codex console resumes the thread id from `thread.started`, so
165
+ later prompts continue one conversation per sketch as Claude's do; project
166
+ `--sandbox` flags are normalised for `exec resume`. Codex item events
167
+ (assistant messages, commands with their output, file changes) render in the
168
+ console. Project panels get `api.openAgent(prompt)`, which opens the Agent
169
+ panel with a draft to review and send, never sending it.
170
+
171
+ ### Changed
172
+
173
+ - **Dragging a node re-renders only what moved.** Each node reads its position
174
+ through its own motion store, and the graph is published once when the drag
175
+ ends rather than copied every frame. At 100 nodes a pointer move costs 1.6 ms
176
+ of script instead of 8.9 (5.6 ms of task time instead of 13.1).
177
+
178
+ - **Node drags apply once per frame.** Moving a node or a selection batches
179
+ pointer moves to one update per animation frame instead of one per event.
180
+
181
+ - **Identical output stops invalidating the graph below it.** A node that
182
+ re-cooks and commits the same values (compared structurally; the same
183
+ object reference counts as changed, since it may be mutated in place) keeps
184
+ its output version, and a node stale only because of that upstream re-cook
185
+ is skipped. A node whose own parameters, code or wiring changed always
186
+ cooks, and `node.earlyCutoff = false` opts a node out. The cook status
187
+ carries the count as `cutOff`. Python projects get the matching half by
188
+ keying their stage cache on content; cloud-plots does (see its
189
+ `runtime/node_cli.py`). There, a no-op edit to `area-filter-mask` now costs
190
+ 2 stage calls and 47 ms instead of 13 calls and 866 ms.
191
+
192
+ - **What a Viewer shows cooks first.** A pass ran in plain topological order,
193
+ so a sink nobody was looking at (an export, a plot check, the mockup) could
194
+ run ahead of the node on screen. Now the selected or pinned node of each open
195
+ Viewer and everything it depends on cook first, and the rest of the pass runs
196
+ after, in the same order as before. With no Viewer (the CLI, tests, cook-all)
197
+ nothing changes. On cloud-plots, a Viewer on `hatch-curves` showed its result
198
+ after 3.4 s instead of 7.4 s on a cold cook.
199
+
200
+ - **An edit cancels the stage it supersedes.** Changing a parameter while a
201
+ long Python stage runs used to wait for that stage, and then for every
202
+ request queued behind it. Now the superseded cook is aborted: its request is
203
+ withdrawn from the worker (dropped if queued, interrupted with SIGINT if
204
+ running, killed if it does not answer), its result is never applied, and the
205
+ pass restarts from the edit. The cook strip shows how many cooks were
206
+ superseded. Measured on cloud-plots, an edit during a 12 s stage now lands in
207
+ 0.6 s instead of 10.9 s. Project workers should answer an interrupt with
208
+ `{"cancelled": true}` to stay warm; see `doc/PROJECT_AUTHORING.md`.
209
+
210
+ ### Fixed
211
+
212
+ - **Three wire and runtime fixes.** Studio's browser-shell adapter sends
213
+ execution options (stdin, timeout, cwd, env) at the top level of the
214
+ `/api/shell` body again; nested under `options` the route dropped them. A
215
+ Switch node's `index` is a document prop, serializes, and re-routes on cook.
216
+ Project CLI instances of one module share a single executor build, so one
217
+ cannot import the `.mjs` while another rewrites it.
218
+
5
219
  ## 0.8.0 — 2026-10-10
6
220
 
7
221
  ### Added
package/DESIGN.md CHANGED
@@ -109,6 +109,8 @@ This document contains both current product rules and intended direction. Sectio
109
109
  ## Components
110
110
 
111
111
  - **Current:** `PortEditor`, `JsonTree`, `ColorPicker`, `CoreValue`, `StructuredValue`, Viewer image zoom/pan, geometry summaries/previews, `SceneViewport` with orbit/track/dolly camera controls, and the type renderer registry. Scene rendering currently shows wireframes and points; lights are represented but do not imply shaded rendering.
112
+ - **Canvas previews:** Projects may opt into readable first-output previews on graph nodes with `settings.nodePreviews: true` in `cascade.json`. The canvas reuses `CoreValue` in compact, read-only mode, including project type renderers; the default remains the compact computational graph. A serialized Dockview layout in `settings.workspace` may also suggest the first-open workspace, but a browser's saved layout always wins.
113
+ - **Group-aware cleanup:** View → Clean Up Layout treats each group as a visual cluster. It arranges and measures members first, fits the frame around them, then places clusters in the graph's top-to-bottom flow. Nested groups stay nested, wide source ranks wrap, and standalone notes move to a clear margin. The command changes positions and group sizes only; membership and subnet hierarchy remain authored data.
112
114
  - **Planned:** a shared type-value presentation shell, structured JSON editing, richer image/asset inspection, a Viewer output list, and texture inspection after texture values exist.
113
115
  - Variants and states: `compact`, `inspect`, `view`; editable/read-only; empty/loading/error/stale; connected source; truncated/expanded
114
116
  - Token/component ownership: `coreTypes.ts` owns semantic type metadata; the presentation registry owns components; Inspector/Viewer only choose context and mode
@@ -173,3 +175,15 @@ This table defines the intended presentation contract. Individual rows may be on
173
175
  - [ ] Whether scene rendering needs shaded GPU surfaces beyond the current CPU wireframe/point view / product / medium impact
174
176
  - [ ] Whether project packages can eventually ship Svelte renderers directly rather than app-side registration / architecture / high impact
175
177
  - [ ] Whether large structured values need virtualization beyond bounded initial expansion / performance / medium impact
178
+
179
+ ## Canvas groups
180
+
181
+ Groups own explicit `containedElements` independently of subnet parenting. Drag
182
+ a frame header to move its members together. Dropping an item’s centre inside a
183
+ frame adds it; dropping outside removes it; the smallest enclosing frame wins
184
+ when frames overlap. The target frame highlights before release. Moving a frame
185
+ does not collect stationary items it passes over. Nested contents move once.
186
+ Membership and positions persist together and share a gesture’s undo snapshot.
187
+ Deleting a frame leaves its contents alive. Unselected wires are neutral grey;
188
+ selection restores their type colour. Preview cards use one surface with
189
+ controls appearing on hover or selection.
package/README.md CHANGED
@@ -11,6 +11,7 @@ under the MIT license. [Getting started and features](https://cascade.field.io).
11
11
  - Deterministic custom-node definitions that tools can inspect without running user code.
12
12
  - An environment-neutral runtime for Node services and UI-free browser applications.
13
13
  - A standalone browser player: build static pages and embeddable sketches without a Studio server.
14
+ - Shareable editors: `cascade export` builds a static site where someone else can change published parameters, save scenes and export, without Studio or an account.
14
15
  - A Studio compatibility controller that already presents deterministic definitions alongside dynamic project nodes while its graph engine migrates to the neutral runtime.
15
16
  - Project-native `.cascade` files, assets, presets, and Git-backed version history.
16
17
  - Nested subnets with persistent hierarchy.
@@ -25,31 +26,45 @@ under the MIT license. [Getting started and features](https://cascade.field.io).
25
26
 
26
27
  Cascade separates the generative algorithm from the platform. Custom nodes describe stages of a pipeline; the runtime schedules and validates them; hosts supply environment-specific capabilities; Studio is only one possible frontend.
27
28
 
28
- ## New in 0.5
29
-
30
- Build a visual system once, then use its supported host for print, stills,
31
- motion frames or an interactive web embed. This release adds the standalone
32
- player and hardens the geometry, simulation and scene tools added during 0.4:
33
-
34
- - **Web delivery:** `cascade build` packages a compatible graph and its explicit
35
- assets. Embeds have independent runtimes, playback, parameter/input controls,
36
- image downloads and disposal; no editor or Cascade API is required.
37
- - **Geometry and subnets:** compose shapes, transforms and copies through one
38
- geometry type; organize reusable networks with typed Input/Output boundaries.
39
- - **Particles and feedback:** wire sources, forces and a solver, retain bounded
40
- history, and turn particle trails into geometry for SVG or raster output.
41
- Checkpoint reuse now preserves complete trails; nested Feedback respects loop
42
- ownership and dependency order.
43
- - **Scenes and cameras:** assemble geometry, a camera and lights, inspect in the
44
- 3D Viewer, and use shared camera math for output. Rendering currently draws
45
- wireframes and points; lights do not yet shade surfaces.
46
- - **Agent-ready rendering:** static node checks, finite render timeouts and JSON
47
- image manifests let an agent edit, render and inspect results. Dawn is optional
48
- native WebGPU for the Node host, not a browser emulator or model integration.
49
-
50
- Studio now uses only its active Dockview layout; the unreachable old window UI
51
- has been removed. No new dependencies or graph engine were introduced for the
52
- player. See the [changelog](CHANGELOG.md) for release details.
29
+ ## Quick start
30
+
31
+ ```bash
32
+ npm install -g @field/cascade
33
+ cascade new my-sketch # scaffolds ~/Documents/Cascade/my-sketch and opens Studio
34
+ cd ~/Documents/Cascade/my-sketch && npm install
35
+ cascade . # reopen it later
36
+ cascade run index.cascade --frames 1 --json # render headlessly
37
+ ```
38
+
39
+ The npm package is at 0.8.0. The 0.9 commands below (`export`, `publish`, `freeze`, `scene`) need a checkout of this repository until 0.9 is published.
40
+
41
+ ## New in 0.9: shareable editors
42
+
43
+ `cascade export` turns a graph into a small static website: a viewer, the parameters you chose to publish, presets, scene files and an export button per output. Send the link and someone without Studio can change your scene, save it as a scene file and send it back.
44
+
45
+ ```bash
46
+ cascade publish index.cascade spec.capMm --label "Cap height" --min 3 --max 60 --unit mm
47
+ cascade freeze index.cascade moment --output moment --fields photos[0],instant
48
+ cascade export index.cascade --plan # what ships and what stays
49
+ cascade export index.cascade --out export/site
50
+ cascade export index.cascade --out export/site --deploy vercel --project my-editor
51
+ ```
52
+
53
+ In Studio, the `share` toggle beside a parameter in the Inspector publishes it, with a label, group and range. Scenes (`*.scene.json`) open in the editor, in Studio and in the CLI (`cascade scene`, `cascade run --scene`). The editor cooks in a module worker, so a slow stage does not stall the page.
54
+
55
+ <img src="https://cascade.field.io/img/inspector-share@2x.webp" width="360" alt="The Studio Inspector with share buttons beside each parameter">
56
+
57
+ The export is an allowlist. It ships the subgraph the outputs need and the assets you name, refuses live sources until you freeze the fields you want, refuses Python, licensed and ignored files, and scans the built site for credentials and local paths. Read [Shareable editors](doc/EDITOR_EXPORT.md) before sharing anything.
58
+
59
+ **Cloud Type** is the first exported editor: the dotted headline generator for FIELD's Human First book. Try it at [cloud-type.vercel.app](https://cloud-type.vercel.app); the project is at [marcuswendt/cloud-type](https://github.com/marcuswendt/cloud-type).
60
+
61
+ ![Cloud Type, an editor exported from a Cascade graph](https://cascade.field.io/img/cloud-type@2x.webp)
62
+
63
+ Large graphs stay readable when they open as a few stages with the detail in subnets. The cloud-plots print graph has 98 nodes and opens as seven.
64
+
65
+ ![The cloud-plots graph in Studio, seven stage nodes](https://cascade.field.io/img/graph-stages@2x.webp)
66
+
67
+ 0.9.1 also fixes a fresh checkout's build: `npm run build` compiles the workspace packages before vite, so `dist/` is never left without a CLI. See the [changelog](CHANGELOG.md).
53
68
 
54
69
  ## Install
55
70
 
@@ -426,6 +441,7 @@ trusted-host session; an untrusted remote bind does not expose them.
426
441
  - [Design source of truth](DESIGN.md)
427
442
  - [Architecture](ARCHITECTURE.md)
428
443
  - [Browser player](doc/WEB_PLAYER.md)
444
+ - [Shareable editors](doc/EDITOR_EXPORT.md)
429
445
  - [September quality review and sketch verification](doc/QUALITY_REVIEW_2026-09.md)
430
446
  - [Subnet and shell specification](spec/CASCADE_SUBNET_AND_SHELL_SPEC.md)
431
447