@field/cascade 0.8.0 → 0.11.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/AGENTS.md +36 -3
- package/CHANGELOG.md +401 -0
- package/DESIGN.md +14 -0
- package/README.md +41 -26
- package/dist/assets/CodeEditor-4O7FQ__R.js +623 -0
- package/dist/assets/CodePanel-BU-autmq.js +2 -0
- package/dist/assets/{CustomNodeDialog-BQbEhIwL.js → CustomNodeDialog-BRpDfOV5.js} +1 -1
- package/dist/assets/OpenGraphDialog-BwbRlC0X.js +1 -0
- package/dist/assets/ProjectSettings-DLOXLxcA.js +2 -0
- package/dist/assets/SettingsDialog-Bz8JxISH.js +1 -0
- package/dist/assets/{VersionHistoryDialog-D6VBzSQ0.js → VersionHistoryDialog-D5Z0nJ5-.js} +2 -2
- package/dist/assets/{core-BInLG4gw.js → core-Yqi0Ni61.js} +8 -8
- package/dist/assets/{cssMode-DfR2qmYG.js → cssMode-CxUzc4vp.js} +1 -1
- package/dist/assets/definitions-GreEMXLV.js +1 -0
- package/dist/assets/{editor.api-Ck8_vgQV.js → editor.api-BNFb25CX.js} +1 -1
- package/dist/assets/{freemarker2-fVn10Wn3.js → freemarker2-0ZDnWxeM.js} +1 -1
- package/dist/assets/geo-u0n_jOsD.js +1 -0
- package/dist/assets/{handlebars-BCSchLT2.js → handlebars-Cy18MoaD.js} +1 -1
- package/dist/assets/{html-CVpSv_k9.js → html-B-2Dx7nq.js} +1 -1
- package/dist/assets/{htmlMode-Da4ESTv0.js → htmlMode-DUAc9B_d.js} +1 -1
- package/dist/assets/{image-BLn--oSF.js → image-cAa-Nu9O.js} +3 -3
- package/dist/assets/index-5ZtDAuy2.js +220 -0
- package/dist/assets/index-7vae6YFC.css +1 -0
- package/dist/assets/index-client-DqYmKstU.js +1 -0
- package/dist/assets/{javascript-BpX0Gvcf.js → javascript-DeQsDqP5.js} +1 -1
- package/dist/assets/{jsonMode-CsLqaou7.js → jsonMode-BiFwJVSk.js} +1 -1
- package/dist/assets/legacy-CTEeXeqF.js +2 -0
- package/dist/assets/{liquid-efUz51Wf.js → liquid-BLoHH68a.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-DCi5-K0n.js → lspLanguageFeatures-CNFgm1Kv.js} +1 -1
- package/dist/assets/math-DioIQOPJ.js +1 -0
- package/dist/assets/{mdx-DP_sjGVy.js → mdx-CFXQVNfs.js} +1 -1
- package/dist/assets/pop-DC_TQG9t.js +1 -0
- package/dist/assets/{python-aAuP3LUi.js → python-Cf7S7p2E.js} +1 -1
- package/dist/assets/{razor-7M6sMmC5.js → razor-CMHBcG-g.js} +1 -1
- package/dist/assets/studioScenes-8sq9FfFg.js +1 -0
- package/dist/assets/{tsMode-Bf4CnoYK.js → tsMode-BEih0GDj.js} +1 -1
- package/dist/assets/{typescript-ddhYBGyT.js → typescript-COEKYD_a.js} +1 -1
- package/dist/assets/{workers-X5la8DDT.js → workers-BNhAhMNn.js} +1 -1
- package/dist/assets/{xml-BzbXa3Ps.js → xml-CPiMpnPl.js} +1 -1
- package/dist/assets/{yaml-CXs-VzxL.js → yaml-Bgp1ITLR.js} +1 -1
- package/dist/cli/Graph-ZJJTRQTM.js +2975 -0
- package/dist/cli/chunk-2KXB47FP.js +115 -0
- package/dist/cli/chunk-35D343DC.js +1447 -0
- package/dist/cli/chunk-36P5K3SD.js +631 -0
- package/dist/cli/chunk-3JTJHF7V.js +267 -0
- package/dist/cli/chunk-4UDFYF5G.js +132 -0
- package/dist/cli/chunk-53NMBJAO.js +35 -0
- package/dist/cli/chunk-A4OAMOZH.js +310 -0
- package/dist/cli/chunk-BIJO5OFS.js +71 -0
- package/dist/cli/chunk-BP7UKF36.js +376 -0
- package/dist/cli/chunk-CKS2FQWR.js +89 -0
- package/dist/cli/chunk-CO22XHNG.js +593 -0
- package/dist/cli/chunk-D6BUOHUG.js +634 -0
- package/dist/cli/chunk-DEQSEFFH.js +153 -0
- package/dist/cli/chunk-DUIUFVU2.js +241 -0
- package/dist/cli/chunk-EUIAC3U3.js +3006 -0
- package/dist/cli/chunk-FCDXJ6EK.js +2208 -0
- package/dist/cli/chunk-GFS6W3C5.js +308 -0
- package/dist/cli/chunk-HFHWYL55.js +139 -0
- package/dist/cli/chunk-HSNOBIVT.js +263 -0
- package/dist/cli/chunk-ICH7N5PN.js +26 -0
- package/dist/cli/chunk-J7VK7MNF.js +418 -0
- package/dist/cli/chunk-KH4MUBKF.js +1551 -0
- package/dist/cli/chunk-MIIEFUGG.js +623 -0
- package/dist/cli/chunk-OWWBYLHC.js +136 -0
- package/dist/cli/chunk-POMMNKZZ.js +672 -0
- package/dist/cli/chunk-QBBKRNGY.js +90 -0
- package/dist/cli/chunk-QQPA2ZHH.js +273 -0
- package/dist/cli/chunk-RLCAJBVR.js +224 -0
- package/dist/cli/chunk-RQZ4SX5R.js +1125 -0
- package/dist/cli/chunk-RUU3YWXU.js +99 -0
- package/dist/cli/chunk-RXDIMXN5.js +98 -0
- package/dist/cli/chunk-SGJAET2L.js +197 -0
- package/dist/cli/chunk-VVGSLVSF.js +151 -0
- package/dist/cli/chunk-WD62JIP6.js +118 -0
- package/dist/cli/chunk-WIH4TEIS.js +104 -0
- package/dist/cli/chunk-WKURDVYP.js +1119 -0
- package/dist/cli/chunk-WPUDGEFY.js +20 -0
- package/dist/cli/chunk-XWDSKG7N.js +1301 -0
- package/dist/cli/chunk-YAT5Y25U.js +121 -0
- package/dist/cli/chunk-ZL4JTG5Y.js +37 -0
- package/dist/cli/cliCommands-UQSFGEHF.js +3464 -0
- package/dist/cli/commands-Q23M26QM.js +1292 -0
- package/dist/cli/definitions-HF2FTHYU.js +32 -0
- package/dist/cli/doctorCommand-B7BPQMN6.js +76 -0
- package/dist/cli/edit-JHCPTQFT.js +28 -0
- package/dist/cli/editorCommands-UIF5YLUZ.js +33 -0
- package/dist/cli/encode-HAUZTYPT.js +17 -0
- package/dist/cli/frames-LSAUBZ7P.js +16 -0
- package/dist/cli/geo-4RNK3QVN.js +43 -0
- package/dist/cli/graphCommands-6BMAKGQE.js +184 -0
- package/dist/cli/graphFile-VPSQ6OF7.js +286 -0
- package/dist/cli/headlessCanvas-5XLDZT7M.js +15 -0
- package/dist/cli/helpCommand-3VRE3KVO.js +155 -0
- package/dist/cli/index.js +106 -14207
- package/dist/cli/math-ZRMLKU2D.js +16 -0
- package/dist/cli/mcp-ZLEEMYGF.js +164 -0
- package/dist/cli/parity-KINARCP2.js +328 -0
- package/dist/cli/pop-USDFXB7H.js +39 -0
- package/dist/cli/project-K3QIPGBB.js +12 -0
- package/dist/cli/projectDefinition-DMTZN2NE.js +27 -0
- package/dist/cli/projectRuntime-Z5PJOH47.js +48 -0
- package/dist/cli/registerStandardNodes-S2VLMF6J.js +3081 -0
- package/dist/cli/render-YURAPPUI.js +436 -0
- package/dist/cli/runCommand-PI764LEG.js +198 -0
- package/dist/cli/runner-RA6UKEPD.js +37 -0
- package/dist/cli/runtime/image.ts +277 -0
- package/dist/cli/runtime/stage.ts +74 -11
- package/dist/cli/stageRunner-KUNIMQKJ.js +10 -0
- package/dist/cli/verbs-RCE3K4VQ.js +19 -0
- package/dist/cli/webBuild-GT4PZT5D.js +37 -0
- package/dist/contracts/bundle.d.ts +75 -0
- package/dist/contracts/bundle.js +112 -0
- package/dist/contracts/definition.d.ts +67 -4
- package/dist/contracts/document.d.ts +29 -0
- package/dist/contracts/documentFormat.d.ts +18 -0
- package/dist/contracts/documentFormat.js +195 -0
- package/dist/contracts/editor.d.ts +189 -0
- package/dist/contracts/editor.js +2 -0
- package/dist/contracts/index.d.ts +3 -0
- package/dist/contracts/index.js +3 -0
- package/dist/contracts/validate.js +59 -3
- package/dist/contracts/values.d.ts +3 -3
- package/dist/contracts/values.js +1 -0
- package/dist/image.d.ts +141 -0
- package/dist/image.js +127 -0
- package/dist/index.html +4 -4
- package/dist/player/app.js +17 -5
- package/dist/player/editor.js +1919 -0
- package/dist/player/editorEngine.js +477 -0
- package/dist/runtime/builtins/core/bundle.d.ts +70 -0
- package/dist/runtime/builtins/core/bundle.js +81 -0
- package/dist/runtime/builtins/core/index.d.ts +3 -2
- package/dist/runtime/builtins/core/index.js +6 -2
- package/dist/runtime/builtins/core/routing.d.ts +27 -0
- package/dist/runtime/builtins/core/routing.js +28 -0
- package/dist/runtime/builtins/headless.d.ts +19 -0
- package/dist/runtime/builtins/headless.js +25 -0
- package/dist/runtime/builtins/image/contactSheet.d.ts +226 -0
- package/dist/runtime/builtins/image/contactSheet.js +199 -0
- package/dist/runtime/builtins/image/index.d.ts +9 -0
- package/dist/runtime/builtins/image/index.js +9 -0
- package/dist/runtime/edit/document.d.ts +94 -0
- package/dist/runtime/edit/document.js +194 -0
- package/dist/runtime/edit/graphEditor.d.ts +223 -0
- package/dist/runtime/edit/graphEditor.js +893 -0
- package/dist/runtime/edit/index.d.ts +12 -0
- package/dist/runtime/edit/index.js +6 -0
- package/dist/runtime/edit/layout.d.ts +50 -0
- package/dist/runtime/edit/layout.js +126 -0
- package/dist/runtime/edit/operations.d.ts +65 -0
- package/dist/runtime/edit/operations.js +57 -0
- package/dist/runtime/edit/parameters.d.ts +75 -0
- package/dist/runtime/edit/parameters.js +284 -0
- package/dist/runtime/edit/read.d.ts +35 -0
- package/dist/runtime/edit/read.js +65 -0
- package/dist/runtime/editor/index.d.ts +104 -0
- package/dist/runtime/editor/index.js +439 -0
- package/dist/runtime/expressions/bundlePaths.d.ts +37 -0
- package/dist/runtime/expressions/bundlePaths.js +55 -0
- package/dist/runtime/expressions/index.d.ts +2 -0
- package/dist/runtime/expressions/index.js +1 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/params/animator.d.ts +5 -0
- package/dist/runtime/params/animator.js +16 -0
- package/dist/runtime/runtime.js +238 -12
- package/dist/runtime/seed.d.ts +29 -0
- package/dist/runtime/seed.js +52 -0
- package/dist/runtime/types.d.ts +12 -0
- package/dist/stage.js +43 -9
- package/dist/studio/panel.d.ts +2 -0
- package/doc/CLI_REFERENCE.md +171 -0
- package/doc/EDITOR_EXPORT.md +235 -0
- package/doc/HEADLESS_GPU.md +27 -0
- package/doc/MCP.md +69 -0
- package/doc/NODE_REFERENCE.md +208 -0
- package/doc/PROJECT_AUTHORING.md +258 -1
- package/package.json +29 -8
- package/dist/assets/CodeEditor-BEk-kIBd.js +0 -623
- package/dist/assets/CodePanel-CeSdjXkg.js +0 -2
- package/dist/assets/ExportDialog-CjTbbTZJ.js +0 -358
- package/dist/assets/ExportDialog-DOq0flMV.css +0 -1
- package/dist/assets/OpenGraphDialog-DCwH9itM.js +0 -1
- package/dist/assets/ProjectSettings-Dg7M5xt9.js +0 -2
- package/dist/assets/SettingsDialog-e7GgsjB9.js +0 -1
- package/dist/assets/definitions-DZpOjWKR.js +0 -1
- package/dist/assets/geo-D2VPjAdt.js +0 -1
- package/dist/assets/index-CMiBdEuT.js +0 -212
- package/dist/assets/index-DMIuml9a.css +0 -1
- package/dist/assets/index-client-BI2H82FJ.js +0 -1
- package/dist/assets/legacy-ZA7textG.js +0 -2
- package/dist/assets/math-B6hpxPJO.js +0 -1
- package/dist/assets/pop-CYUIjT6x.js +0 -1
- package/dist/assets/projectSettingsApi-C1WvIwfP.js +0 -1
package/AGENTS.md
CHANGED
|
@@ -35,13 +35,23 @@ my-project/
|
|
|
35
35
|
└── tsconfig.json
|
|
36
36
|
```
|
|
37
37
|
|
|
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.
|
|
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 render <graph.cascade> --node <id>` renders an animation across worker processes (`--workers N`, default cores minus a few) and encodes a half-size H.264 preview (`--final` full size, `--prores` a master); a node must write each frame to its own file (frame in the name, or `saveImage(…, cachePath(…))`), and one that writes a fixed path is refused before the render starts. `cascade projects` shows or sets the default projects directory.
|
|
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
|
+
|
|
42
|
+
For agents working headlessly: `cascade help node <type>` prints a node's ports and description from the installed package; `cascade run <graph> --out <dir> [--out-node <id>]` saves image outputs as `<node>[.<port>].<ext>` (and `run --json` lists them in `data.images`); `cascade.assert.*` nodes fail a run with a readable message; what nodes and stages print is in the run trace under `.cascade/runs/`; `--env NAME=value` replaces a shell prefix; `cascade doctor --fix` builds the Python environment a project declares in `cascade.json` `python`; every MCP tool takes `project` to work in another directory.
|
|
39
43
|
|
|
40
44
|
`cascade build <graph.cascade> --out <new-directory>` exports a static browser
|
|
41
45
|
player. Use repeatable `--asset <project-relative-file>` for inputs whose paths
|
|
42
46
|
are computed in code. Read `doc/WEB_PLAYER.md` before exporting: server stages
|
|
43
47
|
and dynamic modules are not supported, assets must be explicit, and an existing
|
|
44
48
|
output directory is never overwritten. Serve the result over HTTP, not file://.
|
|
49
|
+
`cascade export <graph.cascade> (--plan | --out <dir>)` exports the graph's
|
|
50
|
+
`editor` section (published parameters, outputs, presets) as a shareable static
|
|
51
|
+
editor. Read `doc/EDITOR_EXPORT.md` first. The export is an allowlist: live
|
|
52
|
+
sources must be frozen (`cascade freeze`), and `licensed/`, hidden and
|
|
53
|
+
gitignored files are refused. Scenes round-trip through the editor, Studio and
|
|
54
|
+
`cascade run --scene`.
|
|
45
55
|
The player is an application host under `src/player`, not another graph engine.
|
|
46
56
|
Each embed owns an iframe realm, assets, IO bridge and GPU lifecycle. No Studio
|
|
47
57
|
imports or `/api/*` dependency may enter the static deployment.
|
|
@@ -71,6 +81,14 @@ curl -fsS http://KURO:3030/health
|
|
|
71
81
|
curl -fsS http://KURO:3030/api/graph
|
|
72
82
|
```
|
|
73
83
|
|
|
84
|
+
For a Studio that should stay up, use `cascade serve` instead of a `screen`:
|
|
85
|
+
`cascade serve start <project> --host KURO --port 3030`, then
|
|
86
|
+
`cascade serve status [project] --json`, `logs`, `restart` and `stop`. It keeps
|
|
87
|
+
one supervisor per project, restarts a crashed Studio, and stops the Python
|
|
88
|
+
worker with it. If the host is unavailable (Tailscale down) Studio binds
|
|
89
|
+
`127.0.0.1` and moves back when the host returns; `status` shows the actual
|
|
90
|
+
binding. Never stop or restart a served Studio you did not start.
|
|
91
|
+
|
|
74
92
|
Remote access is explicit: a specific non-loopback `--host` is also the default
|
|
75
93
|
trusted browser hostname. Use `--trusted-host` only when the bind address and
|
|
76
94
|
browser hostname differ. Hostnames are exact and case-insensitive; wildcard
|
|
@@ -203,6 +221,7 @@ type system knows what a `vec2` is; nothing tells it that `offset_x` and
|
|
|
203
221
|
- Studio uses `StudioGraphController` over its compatibility `Graph`/`Node` engine and reuses runtime mechanisms. Custom frontends consume the neutral runtime directly; full Studio migration remains incomplete.
|
|
204
222
|
- User modules are trusted project code, not a sandbox. Static definitions improve tooling and portability, not isolation.
|
|
205
223
|
- Keep legacy support inside the existing Studio/CLI compatibility engine; do not spread compatibility branches into the deterministic runtime.
|
|
224
|
+
- `src/engine`, `src/nodes`, `src/cli` and `src/player` never import the Studio editor (`src/editor`, `src/App.svelte`); the server never imports `src/`. `tests/architecture-layers.test.ts` enforces these and the two above, and allows no new import cycle.
|
|
206
225
|
|
|
207
226
|
## Change workflow
|
|
208
227
|
|
|
@@ -212,9 +231,23 @@ the TypeScript 7 preview until it is stable and the repository gates pass.
|
|
|
212
231
|
1. Add or update a focused regression test.
|
|
213
232
|
2. Make the smallest change at the owning layer.
|
|
214
233
|
3. Prefer deletion or an existing utility over another wrapper.
|
|
215
|
-
4.
|
|
234
|
+
4. While iterating, run the focused test or `npm run verify:fast` (types for src, tests and server, the node reference, the architecture ratchets, and `vitest related` for the files you changed). Before you commit, run `npm run verify`: it builds the packages, then runs the typechecks, `check:packages`, svelte-check, the whole vitest suite, the package tests and the Studio bundle budget, stopping at the first failure. It never touches `dist/`. Run `npm run build` and `npm run build:cli` only when you need the built CLI or Studio; both replace `dist/` only on success, so a failed build leaves the previous CLI working.
|
|
216
235
|
5. For package/public API changes, also test the packed tarball from an empty temporary project.
|
|
217
|
-
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. `
|
|
236
|
+
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. `verify` fails on a stale one (`npm run check:node-reference`).
|
|
237
|
+
7. The ratchets in `tests/architecture-*.test.ts`, `scripts/bundle-budget.mjs` and the test type-error list in `scripts/verify.mjs` only go down. When one fails, fix the code: split the file, move the shared code down a layer, break the cycle, lazy-load the new Studio code. Never add to a list or raise a number; when your change lowers one, lower the number in the same commit.
|
|
238
|
+
|
|
239
|
+
### Where a change goes
|
|
240
|
+
|
|
241
|
+
| To add | Touch |
|
|
242
|
+
| --- | --- |
|
|
243
|
+
| A node in a project | `cascade node <Name>`, then `nodes/<Name>/index.ts` (see "Create a deterministic node") |
|
|
244
|
+
| A built-in node in an existing namespace | `packages/runtime/src/builtins/<ns>/<node>.ts`, its entry in `builtins/<ns>/index.ts`, a test in `packages/runtime/test/`, then `npm run build:node-reference` |
|
|
245
|
+
| A built-in namespace | `packages/runtime/src/builtins/<ns>/` and `builtins/index.ts`; Studio's `src/nodes/<ns>/index.ts` and `library.ts`, and `src/nodes/initializeLibraries.ts`; `scripts/build-node-reference.mjs` |
|
|
246
|
+
| A CLI verb or MCP tool | One row in `src/cli/verbs.ts`, its handler, and its line in `doc/CLI_REFERENCE.md` (plus `doc/MCP.md` for a tool); `tests/cli-verbs.test.ts` checks the docs |
|
|
247
|
+
| A graph edit operation | `packages/runtime/src/edit/operations.ts` and `graphEditor.ts`, then the verb row above |
|
|
248
|
+
| A param type | `packages/contracts/src/values.ts`, `definition.ts`, `validate.ts`; `packages/runtime/src/runtime.ts`; `src/types/coreTypes.ts`, `node.types.ts`, `src/utils/propUtils.ts`; `src/editor/Inspector.svelte`, `CodeEditor.svelte`; `server/src/projectTemplate.ts`; `doc/PROJECT_AUTHORING.md` |
|
|
249
|
+
| A Studio panel | `src/editor/panels/<Name>Panel.svelte` and its `registerPanelComponent` (or lazy) line in `src/editor/dockview/DockviewContainer.svelte`; keep it out of the entry chunk if it is not on first paint |
|
|
250
|
+
| Shared code for the server and the CLI | `server/src/` (the CLI imports it); pure document code such as the `.cascade` formatter (`formatCompactJSON`) lives in `packages/contracts/src/` |
|
|
218
251
|
|
|
219
252
|
Do not add dependencies without a concrete need. Do not create extra packages unless they need independent publication or versioning.
|
|
220
253
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,407 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to Cascade. Newest first.
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## 0.11.0 — 2026-11-07
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`cascade/image`: one node body for the browser and headless.** A
|
|
12
|
+
portable node declaring `capabilities: ['assets']` draws on `surface()` /
|
|
13
|
+
`createCanvas()` (the realm's `OffscreenCanvas` in Studio and an exported
|
|
14
|
+
editor, Skia's under `cascade run`/`render`/MCP), reads with `readImage` /
|
|
15
|
+
`readBytes` and writes with `writeImage` through the assets capability (the
|
|
16
|
+
host picks the stored path), and registers fonts with `registerFont`
|
|
17
|
+
(`FontFace` in a browser realm, Skia's `GlobalFonts` headless). No canvas or
|
|
18
|
+
no declared `assets` is refused with a sentence. Resolved from Cascade's own
|
|
19
|
+
install by Studio, the editor export, the web player and the CLI. This was
|
|
20
|
+
the missing browser image contract that kept commons nodes headless-only:
|
|
21
|
+
commons `plotter-social` (plotter, social-layout, foil ported; source
|
|
22
|
+
frozen) now exports as an editor, and renders pixel-identically to the old
|
|
23
|
+
server nodes headless. `cascade freeze --fields path,...` on an image output
|
|
24
|
+
now ships the image file with the snapshot.
|
|
25
|
+
- **The sketch kit, `@field/cascade-kit` (`packages/kit`).** One package for
|
|
26
|
+
what the sketch projects kept rebuilding: OKLCH colour and gamut mapping,
|
|
27
|
+
k-means palettes in OKLab, seeded random (`Rng`, mulberry32, Python-equal
|
|
28
|
+
`hashParts`) and noise, paper, pen plot documents for a 0.1 mm pen, frames
|
|
29
|
+
to MP4, Cairn and Observatory snapshot loaders, and a disk cache keyed on
|
|
30
|
+
the code's import closure. Each module's tests pin it to the exact bits of
|
|
31
|
+
the copies it replaces. `cascade-kit nodes <provider>` writes the stubs for
|
|
32
|
+
using another project's nodes from a `file:` dependency, replacing the
|
|
33
|
+
`shared/` symlink and hand-copied stubs; `--check` reports drift. Outside the
|
|
34
|
+
core: Cascade does not import it and the published package does not ship
|
|
35
|
+
it. See `doc/KIT.md`. cloud-volumes, commons and cairn-strata-hd use it.
|
|
36
|
+
- **`npm run verify`, one gate for everything.** Packages build, types for
|
|
37
|
+
src, tests and server, `check:packages`, svelte-check, vitest, the package
|
|
38
|
+
tests (192, outside `test:run` until now) and a Studio bundle budget, in
|
|
39
|
+
order, stopping at the first failure; `verify:fast` for the edit loop.
|
|
40
|
+
Architecture ratchets in `tests/architecture-*.test.ts`: the layer rules
|
|
41
|
+
from ARCHITECTURE.md, no new import cycle, no new file over 750 lines, no
|
|
42
|
+
unimported source file, duplicated lines capped. `build-node-reference
|
|
43
|
+
--check` fails on a stale `doc/NODE_REFERENCE.md`.
|
|
44
|
+
- **Ladder, pick, lock.** `cascade ladder <graph> <node> --name
|
|
45
|
+
--vary node.prop=a,b,c | --seeds a,b,c` cooks three to five variants from
|
|
46
|
+
the stored code and writes each image, a labelled contact sheet and
|
|
47
|
+
`ladders/<id>.json` (per variant: graph, params, seed, inputs, output
|
|
48
|
+
fingerprint; the code and git commit once). `cascade pick <ladder> <n>`
|
|
49
|
+
writes the lock from that record at approval without cooking again, so
|
|
50
|
+
`cascade replay` reproduces the approved image pixel for pixel with no
|
|
51
|
+
worktree. Both are MCP tools (`ladder`, `pick`). New built-in
|
|
52
|
+
`cascade.image.ContactSheet` (definition-v1, headless; not yet in Studio):
|
|
53
|
+
images in, one labelled grid out.
|
|
54
|
+
- **`cascade run --out`, outputs as files.** A still run with `--out <dir>`
|
|
55
|
+
copies each image output to `<dir>/<node>[.<port>].<ext>` (it was ignored
|
|
56
|
+
without `--frames`), and `run --json` lists every image output with its file
|
|
57
|
+
in `data.images`. A node with several image outputs writes one file per port
|
|
58
|
+
instead of overwriting itself; a `cascade.core.Null` passing an image counts
|
|
59
|
+
as an output; `--out-node <id>` (repeatable, MCP `outNodes`) saves a
|
|
60
|
+
mid-graph node as well; an absolute `--out` is accepted.
|
|
61
|
+
- **Assertion nodes, `cascade.assert.Range`, `Equals`, `True` and
|
|
62
|
+
`NotBlank`.** A check in the graph that fails `cascade run` (exit 1, and
|
|
63
|
+
`run --json` gives `error.message: "Assertion failed in \"<node>\" …"`)
|
|
64
|
+
when it does not hold: a value in a range, equal to an expected JSON value,
|
|
65
|
+
true, or an image (PNG/PPM) that is not one flat colour or fully
|
|
66
|
+
transparent. Each passes its input through. Headless only for now: the CLI
|
|
67
|
+
registers them, Studio does not (its entry bundle has no room) and shows
|
|
68
|
+
them unresolved. Listed in `doc/NODE_REFERENCE.md`.
|
|
69
|
+
- **MCP: the project directory per call.** Every tool takes an optional
|
|
70
|
+
`project`; the call's paths resolve against it and may not leave it, and
|
|
71
|
+
CLI-backed tools run there. One server started in commons can work on any
|
|
72
|
+
sketch. See `doc/MCP.md`.
|
|
73
|
+
- **`cascade help node [<type>]`, node docs from the package.** Prints a node
|
|
74
|
+
type's inputs, props and outputs (type, default, range, description), where
|
|
75
|
+
it runs and its capabilities, from the definitions bundled in the CLI or
|
|
76
|
+
read statically from the project's `nodes/`; without a type, lists every
|
|
77
|
+
type. Short names work (`Circle`, `NotBlank`); a typo gets suggestions; a
|
|
78
|
+
class-based Studio node says so and points at the shipped
|
|
79
|
+
`doc/NODE_REFERENCE.md`. `--json`, and MCP `node_help`.
|
|
80
|
+
- **Debug output in the run trace, and `--env`.** What a node prints while it
|
|
81
|
+
cooks (console, and its Python stages' stderr, which was shown only with
|
|
82
|
+
`--verbose`) is kept per node in `.cascade/runs/…json` and in
|
|
83
|
+
`run --json` as `data.logs`. A failed run now writes its trace too and
|
|
84
|
+
names it in the error. `cascade run|render --env NAME=value` (MCP `env`)
|
|
85
|
+
sets a variable for the run's stages and render workers without a shell
|
|
86
|
+
prefix; the trace records the names only.
|
|
87
|
+
- **A declared Python environment for stages, and `cascade doctor`.**
|
|
88
|
+
`cascade.json` `"python": { "requirements": ["numpy", "Pillow"] }` (or a
|
|
89
|
+
requirements file) declares what a project's stages import; `cascade
|
|
90
|
+
doctor --fix` builds a venv for it in `.cascade-cache/python/venv`, never
|
|
91
|
+
system-wide, and stages then run under it instead of a bare `python3`. A
|
|
92
|
+
stage call with the environment missing or stale fails naming the fix,
|
|
93
|
+
not later on an ImportError. `cascade doctor` (MCP `doctor`) also checks
|
|
94
|
+
the stage interpreter, ffmpeg and the headless canvas.
|
|
95
|
+
|
|
96
|
+
### Removed
|
|
97
|
+
|
|
98
|
+
- **The Studio's single-file HTML export (File > Export…, ⌘E).** It ran a
|
|
99
|
+
third, minimal engine that understood neither definition-v1, expressions
|
|
100
|
+
nor animation. `cascade build` exports the browser player and `cascade
|
|
101
|
+
export` the shareable editor; the other exports are unchanged. Five unused Studio components and the code-history store only
|
|
102
|
+
they used are gone too.
|
|
103
|
+
|
|
104
|
+
### Changed
|
|
105
|
+
|
|
106
|
+
- **The CLI starts in 30 ms, not 300.** Each verb's handler loads when the
|
|
107
|
+
verb runs and the published bundle is split, so `cascade --version`, the
|
|
108
|
+
graph commands and every child the MCP server spawns no longer load the
|
|
109
|
+
engine, TypeScript, esbuild, sharp and express first (start-up: 3 modules,
|
|
110
|
+
was 225; `--version` 29 ms and 46 MB, was 286 ms and 155 MB).
|
|
111
|
+
- **One verb table, `src/cli/verbs.ts`.** Dispatch, `--help`, `--json`
|
|
112
|
+
handling, the graph commands' options and the MCP tools all read it, so a
|
|
113
|
+
new verb is one row, its handler and its line in `doc/CLI_REFERENCE.md`,
|
|
114
|
+
which now lists every command.
|
|
115
|
+
- `cascade graph list` skips `renders/` and `out/`.
|
|
116
|
+
- The `.cascade` compact formatter has one copy, `formatCompactJSON` in
|
|
117
|
+
`cascade/contracts`, used by Studio, the server and the CLI; the server and
|
|
118
|
+
CLI share one atomic-write helper.
|
|
119
|
+
- **The stage cache is on by default for node cooks.** A stage called from a
|
|
120
|
+
node's cook through `cascade/stage` is treated as pure and cached on its
|
|
121
|
+
code, arguments and input file bytes; a panel's `api.runStage` call is an
|
|
122
|
+
action and is not cached unless declared. A re-cook of
|
|
123
|
+
cloud-plots/relief.cascade went from 4.2 s to 0.45 s (all 17 stage calls
|
|
124
|
+
hit; no Python started). Opt a stage out with
|
|
125
|
+
`exec.stages.cache.exclude`, or everything with `"cache": false`; see
|
|
126
|
+
"The stage cache default" in `doc/PROJECT_AUTHORING.md`.
|
|
127
|
+
|
|
128
|
+
### Fixed
|
|
129
|
+
|
|
130
|
+
- **A node fed a different image of the same size re-cooks.** The input
|
|
131
|
+
fingerprint sampled three values of a typed array and only the dimensions of
|
|
132
|
+
an image, so two same-size images looked identical and a clean node kept
|
|
133
|
+
its old picture. A connected input is now keyed by its producer's output
|
|
134
|
+
version (O(1), exact), and a value set directly on a port is hashed in full.
|
|
135
|
+
- The node and graph file watchers take an injected clock and watcher, and
|
|
136
|
+
their tests no longer sleep on real FSEvents; they had failed in every
|
|
137
|
+
loaded full run.
|
|
138
|
+
- The MCP `locks` tool always answered "no locks command yet": the lock tools
|
|
139
|
+
probed `cascade --help` first and the probe never matched. The probe is
|
|
140
|
+
gone, so `lock`, `replay` and `locks` also spawn one process instead of two.
|
|
141
|
+
|
|
142
|
+
## 0.10.2 — 2026-11-06
|
|
143
|
+
|
|
144
|
+
### Added
|
|
145
|
+
|
|
146
|
+
- **`cascade render`: an animation across worker processes.** `cascade render
|
|
147
|
+
<graph> --node <id> [--frames <range>] [--workers N]` splits the range across
|
|
148
|
+
processes (default: cores minus a few), each pulling contiguous batches from
|
|
149
|
+
one queue, and writes the same `<out>/<node>.<frame>.<ext>` sequence a serial
|
|
150
|
+
`run --frames` writes. A node that writes every frame to one fixed file is
|
|
151
|
+
refused before the other workers start: the first worker renders the first
|
|
152
|
+
two frames alone, and two frames on one path stop the render with the node
|
|
153
|
+
and the path. 144 ripple frames at 540 px on a shared 16-core machine at load
|
|
154
|
+
33-44: 59 s serial, 8-14 s on 8-12 workers, frames byte-identical to the
|
|
155
|
+
serial render.
|
|
156
|
+
- **Preview by default.** An animation render also encodes
|
|
157
|
+
`<out>/<node>.preview.mp4`, half size, H.264 yuv420p with faststart.
|
|
158
|
+
`--final` encodes `<node>.mp4` at full size, `--prores` adds a ProRes
|
|
159
|
+
`<node>.mov` (4444 with alpha when the frames have any, else 422 HQ),
|
|
160
|
+
`--no-video` skips it. ffmpeg is checked before the render, not after.
|
|
161
|
+
- **Progress and ETA.** One line every N frames (`--progress N`, default about
|
|
162
|
+
twenty a render), and the same as a note on a Cairn job with `--job <id>` or
|
|
163
|
+
`CAIRN_JOB` (`cairn jobs update <id> --note`).
|
|
164
|
+
|
|
165
|
+
### Fixed
|
|
166
|
+
|
|
167
|
+
- **Project nodes compile atomically.** The bundle is written beside its name
|
|
168
|
+
and renamed into place, so processes compiling the same node at once never
|
|
169
|
+
import a half-written file.
|
|
170
|
+
|
|
171
|
+
## 0.10.1 — 2026-10-12
|
|
172
|
+
|
|
173
|
+
### Fixed
|
|
174
|
+
|
|
175
|
+
- **A phone never scales the editor page.** The viewport is fixed at the
|
|
176
|
+
device width (`maximum-scale=1`). iOS ignores `user-scalable=no`, so the shell
|
|
177
|
+
also blocks Safari's gesture events and two-finger moves outside the preview,
|
|
178
|
+
and sets `touch-action: manipulation` on controls so a double-tap on a button
|
|
179
|
+
does not zoom. Pinching the preview still zooms the preview. The page clips
|
|
180
|
+
any horizontal overflow, and the header truncates within the screen width.
|
|
181
|
+
|
|
182
|
+
### Added
|
|
183
|
+
|
|
184
|
+
- **Fonts in exported editors.** `editor.fonts` lists OFL-1.1 fonts that
|
|
185
|
+
`cascade export` ships and loads in the page and the engine worker, so
|
|
186
|
+
canvas and panel text draw with the project's font. Other licences and
|
|
187
|
+
`licensed/` files are refused.
|
|
188
|
+
- **`cascade export --deploy vercel --public`** for an editor meant to be
|
|
189
|
+
public: an anonymously readable site is reported as intended instead of
|
|
190
|
+
failing the deploy.
|
|
191
|
+
|
|
192
|
+
## 0.10.0 — 2026-10-12
|
|
193
|
+
|
|
194
|
+
### Added
|
|
195
|
+
|
|
196
|
+
- **The timeline is saved with the graph.** `timeline: { fps, start, end,
|
|
197
|
+
loop }` in the document: Studio's Timeline opens on it and writes it back,
|
|
198
|
+
the runtime uses its fps, and `cascade run --frames timeline` renders its
|
|
199
|
+
range.
|
|
200
|
+
- **`run --frames … --mp4 <file> [--crf N]`** encodes the rendered sequence
|
|
201
|
+
with ffmpeg as H.264 yuv420p at the run's fps, and reports it as `video` in
|
|
202
|
+
the `--json` manifest.
|
|
203
|
+
- **Stage cache keys Cascade owns.** Every Python stage call, Studio or
|
|
204
|
+
headless, is keyed on the stage code (a hash of `exec.stages.sources`), the
|
|
205
|
+
arguments with input files replaced by their content hash, and the Cascade
|
|
206
|
+
version, and its cache state (`hit`, `miss`, `off`) and key are reported on
|
|
207
|
+
every call: in the server log, in `run --json` under `stages`, and in the run
|
|
208
|
+
trace. `exec.stages.cache` turns on a core result cache that verifies the
|
|
209
|
+
files a stored result names before serving it.
|
|
210
|
+
- **Run traces.** Every `cascade run` writes `.cascade/runs/<time>-<graph>.json`
|
|
211
|
+
with each node's time and its stage calls. `run --json` works without
|
|
212
|
+
`--frames`.
|
|
213
|
+
- **Seeds.** `context.seed` (from the document's `seed` and the node id) and
|
|
214
|
+
`context.random()` in both hosts; `cascade run --seed N`.
|
|
215
|
+
- **`cascade parity <graph> [--node] [--tolerance] [--json]`** cooks headless
|
|
216
|
+
twice and through Studio's executor with caches off and reports every node
|
|
217
|
+
output side by side.
|
|
218
|
+
- **Locks and replay.** `cascade lock <graph> <node> --name <name>` records one
|
|
219
|
+
render in `locks/<id>.json`: the graph as cooked, every prop and seed, input
|
|
220
|
+
file hashes, the project's source code (stored by hash in
|
|
221
|
+
`.cascade/objects/`), versions and git state, and a fingerprint of every
|
|
222
|
+
output. `cascade replay <id>` rebuilds that code in a throwaway copy of the
|
|
223
|
+
project and compares fingerprints, without a worktree; `--live` uses the
|
|
224
|
+
current code instead. `cascade lock verify` replays every lock and
|
|
225
|
+
`cascade locks` lists them. All take `--json`.
|
|
226
|
+
|
|
227
|
+
- **`cascade serve`.** `start | stop | restart | status | logs | install |
|
|
228
|
+
uninstall [project]` runs Studio as a supervised background service: one
|
|
229
|
+
lock, record and log per project under `~/.cascade/serve/`, restart with
|
|
230
|
+
backoff after a crash, and a stop that takes the Python worker with it.
|
|
231
|
+
`status --json` reports port, actual host, pids, uptime, version and worker
|
|
232
|
+
state. `install` writes and loads a macOS launchd job.
|
|
233
|
+
- **Host fallback.** When `--host` does not resolve (a MagicDNS name while
|
|
234
|
+
Tailscale is down) or is not on this machine (`EADDRNOTAVAIL`), Studio binds
|
|
235
|
+
`127.0.0.1` (or `--fallback-host`, repeatable) instead of crashing, and moves
|
|
236
|
+
back to the preferred host when it returns.
|
|
237
|
+
- **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`.
|
|
238
|
+
- **`--json` on every command**: one `{ ok, data, warnings }` envelope on stdout.
|
|
239
|
+
- **`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`.
|
|
240
|
+
- The editing API (`GraphEditor`, `readGraph`, the operation types) is exported from `@field/cascade/runtime`.
|
|
241
|
+
|
|
242
|
+
### Changed
|
|
243
|
+
|
|
244
|
+
- `cascade run --frames --json` prints its manifest inside the envelope, as `data`, rather than at the top level.
|
|
245
|
+
|
|
246
|
+
### Fixed
|
|
247
|
+
|
|
248
|
+
- **Headless frame renders no longer start Python per stage per frame.**
|
|
249
|
+
`cascade run` uses the project's warm worker for the whole run, and frames
|
|
250
|
+
after the first re-cook only what the frame changed (`reuse: "strict"`;
|
|
251
|
+
`--fresh` cooks everything). cloud-plots' morph, frames 1–60: 588 s to 5 s,
|
|
252
|
+
byte-identical.
|
|
253
|
+
|
|
254
|
+
- **An edited stage no longer runs its old code in a live Studio.** The warm
|
|
255
|
+
Python worker restarts before the next request when its stage sources
|
|
256
|
+
change, with Python's bytecode cache keyed by the code hash so a quick
|
|
257
|
+
same-length edit is not served from an old `.pyc`.
|
|
258
|
+
|
|
259
|
+
- **A failed build keeps the previous `dist/`.** `npm run build` and
|
|
260
|
+
`build:cli` build into `.dist-staging/` and swap it in only when every step
|
|
261
|
+
passed; the log names the step that failed.
|
|
262
|
+
|
|
263
|
+
## 0.9.2 — 2026-10-12
|
|
264
|
+
|
|
265
|
+
### Added
|
|
266
|
+
|
|
267
|
+
- **Exported editors work on phones.** The preview is full width at the top,
|
|
268
|
+
with pinch, pan and double-tap to fit. Controls sit in a bottom sheet with
|
|
269
|
+
three snap points and folded groups, sized for thumbs (44 px targets, 16 px
|
|
270
|
+
text, steppers). The header is one row with a ⋯ menu. Safe-area insets and
|
|
271
|
+
`100dvh` keep everything clear of Safari's toolbar. Exports and scenes use the
|
|
272
|
+
share sheet, with a download as the fallback. Landscape uses a side panel, and
|
|
273
|
+
desktop is unchanged.
|
|
274
|
+
- **`editor.peek` and `editor.draft`.** These choose the controls kept in reach
|
|
275
|
+
at the sheet's lowest point, and the values cooked while a slider is dragged
|
|
276
|
+
(a lower density, say).
|
|
277
|
+
|
|
278
|
+
## 0.9.1 — 2026-10-11
|
|
279
|
+
|
|
280
|
+
### Added
|
|
281
|
+
|
|
282
|
+
- **Share from the Inspector.** Studio's Inspector has a `share` toggle per
|
|
283
|
+
parameter that publishes it to the exported editor, with label, group and
|
|
284
|
+
min/max/step fields.
|
|
285
|
+
|
|
286
|
+
### Changed
|
|
287
|
+
|
|
288
|
+
- **The exported editor cooks in a module worker** (`editor-worker.js`), so a
|
|
289
|
+
slow stage no longer freezes the page while someone drags a slider.
|
|
290
|
+
|
|
291
|
+
### Fixed
|
|
292
|
+
|
|
293
|
+
- **A fresh tree builds.** `npm run build` compiles the workspace packages
|
|
294
|
+
before vite, and no longer leaves `dist/` without a CLI.
|
|
295
|
+
|
|
296
|
+
## 0.9.0 — 2026-10-11
|
|
297
|
+
|
|
298
|
+
### Added
|
|
299
|
+
|
|
300
|
+
- **Shareable editors (0.9.0).** `cascade export <graph> --out <dir>` builds a
|
|
301
|
+
static editor site from a graph's new `editor` section. It has the published
|
|
302
|
+
parameters (with a UI generated from their types), presets, scene files, one
|
|
303
|
+
export button per declared output, and a read-only inspect view of every
|
|
304
|
+
stage. `--plan` prints the manifest without building, and
|
|
305
|
+
`--deploy vercel` deploys the site and checks that Vercel Authentication is
|
|
306
|
+
on.
|
|
307
|
+
|
|
308
|
+
The export is an allowlist. It ships the subgraph the outputs need and the
|
|
309
|
+
selected assets, and nothing else. It refuses Python and dynamic nodes,
|
|
310
|
+
wired-in live sources, `licensed/`, hidden and gitignored files. It scans the
|
|
311
|
+
built site for credentials, local paths and backend URLs.
|
|
312
|
+
`cascade freeze` snapshots chosen fields of a live source, and
|
|
313
|
+
`cascade publish` marks a prop as a parameter. Scenes (`*.scene.json`) open
|
|
314
|
+
in the editor, in Studio (File › Open/Save Scene) and in the CLI
|
|
315
|
+
(`cascade scene`, `cascade run --scene --write`), with versioned,
|
|
316
|
+
degrade-gracefully matching.
|
|
317
|
+
|
|
318
|
+
The runtime gains `run({ reuse: true })`, an early cutoff for hosts that
|
|
319
|
+
re-run on every edit, and `cascade.core.Frozen`. Node definitions gain
|
|
320
|
+
`source: "live"`. See `doc/EDITOR_EXPORT.md`.
|
|
321
|
+
|
|
322
|
+
- **Bundle ports.** A node can export one `bundle` port carrying named fields
|
|
323
|
+
instead of a dozen loose outputs. A producer declares `fields` (name to type)
|
|
324
|
+
and an optional `schema`; a consumer declares the `fields` it reads, sees only
|
|
325
|
+
those, and in Studio re-cooks only when one of them changed (per-field
|
|
326
|
+
versions on top of early cutoff). Expressions read a wired bundle's fields
|
|
327
|
+
with `ch("format.dpi")`. `cascade.core.Pick` and `cascade.core.Pack` convert
|
|
328
|
+
between bundles and single values. `cascade check` reports unknown fields with
|
|
329
|
+
the nearest declared name, and refuses an absolute read of another node's
|
|
330
|
+
bundle. Studio draws a bundle as one neutral port whose hover and Inspector
|
|
331
|
+
list its fields and values. Bundles reach Python stages as dicts. See
|
|
332
|
+
"Bundle ports" in `doc/PROJECT_AUTHORING.md`.
|
|
333
|
+
|
|
334
|
+
- **Node previews on the canvas.** A project that sets
|
|
335
|
+
`settings.nodePreviews: true` in `cascade.json` shows each node's first
|
|
336
|
+
output as a readable preview card on the graph, refreshed per node cook. The
|
|
337
|
+
same settings can carry a `workspace` used as the first-open dock layout when
|
|
338
|
+
the browser has none saved; a layout that fails to load falls back to the
|
|
339
|
+
built-in one.
|
|
340
|
+
|
|
341
|
+
- **Groups own their contents.** A group frame keeps an explicit
|
|
342
|
+
`containedElements` list, separate from subnet parenting. Drag the frame
|
|
343
|
+
header to move its members (nested contents move once); drop an item's
|
|
344
|
+
centre inside a frame to add it, outside to remove it, and the smallest
|
|
345
|
+
enclosing frame wins. The target frame highlights before release, and
|
|
346
|
+
membership and positions share one undo step. Deleting a frame leaves its
|
|
347
|
+
contents. View → Clean Up Layout now treats each group as a cluster: it lays
|
|
348
|
+
out members first, fits the frame, then places the groups.
|
|
349
|
+
|
|
350
|
+
- **The Agent console keeps a Codex conversation, and panels can hand it a
|
|
351
|
+
draft.** A Codex console resumes the thread id from `thread.started`, so
|
|
352
|
+
later prompts continue one conversation per sketch as Claude's do; project
|
|
353
|
+
`--sandbox` flags are normalised for `exec resume`. Codex item events
|
|
354
|
+
(assistant messages, commands with their output, file changes) render in the
|
|
355
|
+
console. Project panels get `api.openAgent(prompt)`, which opens the Agent
|
|
356
|
+
panel with a draft to review and send, never sending it.
|
|
357
|
+
|
|
358
|
+
### Changed
|
|
359
|
+
|
|
360
|
+
- **Dragging a node re-renders only what moved.** Each node reads its position
|
|
361
|
+
through its own motion store, and the graph is published once when the drag
|
|
362
|
+
ends rather than copied every frame. At 100 nodes a pointer move costs 1.6 ms
|
|
363
|
+
of script instead of 8.9 (5.6 ms of task time instead of 13.1).
|
|
364
|
+
|
|
365
|
+
- **Node drags apply once per frame.** Moving a node or a selection batches
|
|
366
|
+
pointer moves to one update per animation frame instead of one per event.
|
|
367
|
+
|
|
368
|
+
- **Identical output stops invalidating the graph below it.** A node that
|
|
369
|
+
re-cooks and commits the same values (compared structurally; the same
|
|
370
|
+
object reference counts as changed, since it may be mutated in place) keeps
|
|
371
|
+
its output version, and a node stale only because of that upstream re-cook
|
|
372
|
+
is skipped. A node whose own parameters, code or wiring changed always
|
|
373
|
+
cooks, and `node.earlyCutoff = false` opts a node out. The cook status
|
|
374
|
+
carries the count as `cutOff`. Python projects get the matching half by
|
|
375
|
+
keying their stage cache on content; cloud-plots does (see its
|
|
376
|
+
`runtime/node_cli.py`). There, a no-op edit to `area-filter-mask` now costs
|
|
377
|
+
2 stage calls and 47 ms instead of 13 calls and 866 ms.
|
|
378
|
+
|
|
379
|
+
- **What a Viewer shows cooks first.** A pass ran in plain topological order,
|
|
380
|
+
so a sink nobody was looking at (an export, a plot check, the mockup) could
|
|
381
|
+
run ahead of the node on screen. Now the selected or pinned node of each open
|
|
382
|
+
Viewer and everything it depends on cook first, and the rest of the pass runs
|
|
383
|
+
after, in the same order as before. With no Viewer (the CLI, tests, cook-all)
|
|
384
|
+
nothing changes. On cloud-plots, a Viewer on `hatch-curves` showed its result
|
|
385
|
+
after 3.4 s instead of 7.4 s on a cold cook.
|
|
386
|
+
|
|
387
|
+
- **An edit cancels the stage it supersedes.** Changing a parameter while a
|
|
388
|
+
long Python stage runs used to wait for that stage, and then for every
|
|
389
|
+
request queued behind it. Now the superseded cook is aborted: its request is
|
|
390
|
+
withdrawn from the worker (dropped if queued, interrupted with SIGINT if
|
|
391
|
+
running, killed if it does not answer), its result is never applied, and the
|
|
392
|
+
pass restarts from the edit. The cook strip shows how many cooks were
|
|
393
|
+
superseded. Measured on cloud-plots, an edit during a 12 s stage now lands in
|
|
394
|
+
0.6 s instead of 10.9 s. Project workers should answer an interrupt with
|
|
395
|
+
`{"cancelled": true}` to stay warm; see `doc/PROJECT_AUTHORING.md`.
|
|
396
|
+
|
|
397
|
+
### Fixed
|
|
398
|
+
|
|
399
|
+
- **Three wire and runtime fixes.** Studio's browser-shell adapter sends
|
|
400
|
+
execution options (stdin, timeout, cwd, env) at the top level of the
|
|
401
|
+
`/api/shell` body again; nested under `options` the route dropped them. A
|
|
402
|
+
Switch node's `index` is a document prop, serializes, and re-routes on cook.
|
|
403
|
+
Project CLI instances of one module share a single executor build, so one
|
|
404
|
+
cannot import the `.mjs` while another rewrites it.
|
|
405
|
+
|
|
5
406
|
## 0.8.0 — 2026-10-10
|
|
6
407
|
|
|
7
408
|
### 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
|
-
##
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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.11.0 and includes every command below. 0.11 adds `cascade/image`, `ladder`/`pick`, `run --out`, assertion nodes, `help node` and `doctor`; see the [changelog](CHANGELOG.md).
|
|
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
|
+

|
|
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
|
+

|
|
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
|
|
|
@@ -368,7 +383,6 @@ a second set of node algorithms.
|
|
|
368
383
|
| Embedded runtime | `cascade/runtime` is the neutral definition-v1 API for Node and browser hosts. It does not load Studio or interpret dynamic nodes. |
|
|
369
384
|
| Static browser player | `cascade build` exports definition-v1 browser/portable graphs with assets and optional browser WebGPU. No server operations, dynamic modules or project Studio panels. Same-origin JavaScript controls; ordinary cross-origin iframe embeds. |
|
|
370
385
|
| GPU | Studio and the optional Dawn CLI host provide a shared device, adapter metadata, limits, and per-node caches. Portable GPU nodes render offscreen and explicitly read RGBA8 pixels through `cascade/gpu`; graph ports still carry images. See [headless GPU rendering](doc/HEADLESS_GPU.md). |
|
|
371
|
-
| Studio HTML export | The older Studio exporter uses a separate minimal runtime and supports only a subset of graph behavior. Use `cascade build` for supported definition-v1 web deployment. |
|
|
372
386
|
| External services | Project-owned and optional. Cascade itself requires no paid provider or model subscription. |
|
|
373
387
|
|
|
374
388
|
## Repository map
|
|
@@ -426,6 +440,7 @@ trusted-host session; an untrusted remote bind does not expose them.
|
|
|
426
440
|
- [Design source of truth](DESIGN.md)
|
|
427
441
|
- [Architecture](ARCHITECTURE.md)
|
|
428
442
|
- [Browser player](doc/WEB_PLAYER.md)
|
|
443
|
+
- [Shareable editors](doc/EDITOR_EXPORT.md)
|
|
429
444
|
- [September quality review and sketch verification](doc/QUALITY_REVIEW_2026-09.md)
|
|
430
445
|
- [Subnet and shell specification](spec/CASCADE_SUBNET_AND_SHELL_SPEC.md)
|
|
431
446
|
|