@field/cascade 0.10.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.
Files changed (133) hide show
  1. package/AGENTS.md +20 -3
  2. package/CHANGELOG.md +187 -0
  3. package/README.md +1 -2
  4. package/dist/assets/{CodeEditor-DSZBpzdy.js → CodeEditor-4O7FQ__R.js} +4 -4
  5. package/dist/assets/{CodePanel-sY6sZa7B.js → CodePanel-BU-autmq.js} +2 -2
  6. package/dist/assets/{CustomNodeDialog-BRKnqZhp.js → CustomNodeDialog-BRpDfOV5.js} +1 -1
  7. package/dist/assets/{OpenGraphDialog-ZsgL-iwr.js → OpenGraphDialog-BwbRlC0X.js} +1 -1
  8. package/dist/assets/{ProjectSettings-Cw17nNe3.js → ProjectSettings-DLOXLxcA.js} +1 -1
  9. package/dist/assets/{SettingsDialog-p25h3tj0.js → SettingsDialog-Bz8JxISH.js} +1 -1
  10. package/dist/assets/{VersionHistoryDialog-DzFLUotB.js → VersionHistoryDialog-D5Z0nJ5-.js} +1 -1
  11. package/dist/assets/{core-BICrEt0y.js → core-Yqi0Ni61.js} +1 -1
  12. package/dist/assets/{cssMode-D7TXw57I.js → cssMode-CxUzc4vp.js} +1 -1
  13. package/dist/assets/{definitions-DUww2Rt-.js → definitions-GreEMXLV.js} +1 -1
  14. package/dist/assets/{editor.api-DvkCO3ko.js → editor.api-BNFb25CX.js} +1 -1
  15. package/dist/assets/{freemarker2-BA2lxsF1.js → freemarker2-0ZDnWxeM.js} +1 -1
  16. package/dist/assets/geo-u0n_jOsD.js +1 -0
  17. package/dist/assets/{handlebars-BcDiyPd8.js → handlebars-Cy18MoaD.js} +1 -1
  18. package/dist/assets/{html-C7O4TyhX.js → html-B-2Dx7nq.js} +1 -1
  19. package/dist/assets/{htmlMode-WaDGF3Mj.js → htmlMode-DUAc9B_d.js} +1 -1
  20. package/dist/assets/{image-DR4oeyJB.js → image-cAa-Nu9O.js} +1 -1
  21. package/dist/assets/{index-DyvDC6pS.js → index-5ZtDAuy2.js} +42 -41
  22. package/dist/assets/{javascript-CpIEK7tz.js → javascript-DeQsDqP5.js} +1 -1
  23. package/dist/assets/{jsonMode-B2FltW0f.js → jsonMode-BiFwJVSk.js} +1 -1
  24. package/dist/assets/{liquid-CN6FFHZE.js → liquid-BLoHH68a.js} +1 -1
  25. package/dist/assets/{lspLanguageFeatures-QhV9XtLp.js → lspLanguageFeatures-CNFgm1Kv.js} +1 -1
  26. package/dist/assets/math-DioIQOPJ.js +1 -0
  27. package/dist/assets/{mdx-DE89pafV.js → mdx-CFXQVNfs.js} +1 -1
  28. package/dist/assets/pop-DC_TQG9t.js +1 -0
  29. package/dist/assets/{python-ByTllTB9.js → python-Cf7S7p2E.js} +1 -1
  30. package/dist/assets/{razor-USYlRRCE.js → razor-CMHBcG-g.js} +1 -1
  31. package/dist/assets/{tsMode-BXpN8iUz.js → tsMode-BEih0GDj.js} +1 -1
  32. package/dist/assets/{typescript-DInBjGQQ.js → typescript-COEKYD_a.js} +1 -1
  33. package/dist/assets/{workers-C7Ye5B7D.js → workers-BNhAhMNn.js} +1 -1
  34. package/dist/assets/{xml-U0Uocqyo.js → xml-CPiMpnPl.js} +1 -1
  35. package/dist/assets/{yaml-CBw_PVYf.js → yaml-Bgp1ITLR.js} +1 -1
  36. package/dist/cli/Graph-ZJJTRQTM.js +2975 -0
  37. package/dist/cli/chunk-2KXB47FP.js +115 -0
  38. package/dist/cli/chunk-35D343DC.js +1447 -0
  39. package/dist/cli/chunk-36P5K3SD.js +631 -0
  40. package/dist/cli/chunk-3JTJHF7V.js +267 -0
  41. package/dist/cli/chunk-4UDFYF5G.js +132 -0
  42. package/dist/cli/chunk-53NMBJAO.js +35 -0
  43. package/dist/cli/chunk-A4OAMOZH.js +310 -0
  44. package/dist/cli/chunk-BIJO5OFS.js +71 -0
  45. package/dist/cli/chunk-BP7UKF36.js +376 -0
  46. package/dist/cli/chunk-CKS2FQWR.js +89 -0
  47. package/dist/cli/chunk-CO22XHNG.js +593 -0
  48. package/dist/cli/chunk-D6BUOHUG.js +634 -0
  49. package/dist/cli/chunk-DEQSEFFH.js +153 -0
  50. package/dist/cli/chunk-DUIUFVU2.js +241 -0
  51. package/dist/cli/chunk-EUIAC3U3.js +3006 -0
  52. package/dist/cli/chunk-FCDXJ6EK.js +2208 -0
  53. package/dist/cli/chunk-GFS6W3C5.js +308 -0
  54. package/dist/cli/chunk-HFHWYL55.js +139 -0
  55. package/dist/cli/chunk-HSNOBIVT.js +263 -0
  56. package/dist/cli/chunk-ICH7N5PN.js +26 -0
  57. package/dist/cli/chunk-J7VK7MNF.js +418 -0
  58. package/dist/cli/chunk-KH4MUBKF.js +1551 -0
  59. package/dist/cli/chunk-MIIEFUGG.js +623 -0
  60. package/dist/cli/chunk-OWWBYLHC.js +136 -0
  61. package/dist/cli/chunk-POMMNKZZ.js +672 -0
  62. package/dist/cli/chunk-QBBKRNGY.js +90 -0
  63. package/dist/cli/chunk-QQPA2ZHH.js +273 -0
  64. package/dist/cli/chunk-RLCAJBVR.js +224 -0
  65. package/dist/cli/chunk-RQZ4SX5R.js +1125 -0
  66. package/dist/cli/chunk-RUU3YWXU.js +99 -0
  67. package/dist/cli/chunk-RXDIMXN5.js +98 -0
  68. package/dist/cli/chunk-SGJAET2L.js +197 -0
  69. package/dist/cli/chunk-VVGSLVSF.js +151 -0
  70. package/dist/cli/chunk-WD62JIP6.js +118 -0
  71. package/dist/cli/chunk-WIH4TEIS.js +104 -0
  72. package/dist/cli/chunk-WKURDVYP.js +1119 -0
  73. package/dist/cli/chunk-WPUDGEFY.js +20 -0
  74. package/dist/cli/chunk-XWDSKG7N.js +1301 -0
  75. package/dist/cli/chunk-YAT5Y25U.js +121 -0
  76. package/dist/cli/chunk-ZL4JTG5Y.js +37 -0
  77. package/dist/cli/cliCommands-UQSFGEHF.js +3464 -0
  78. package/dist/cli/commands-Q23M26QM.js +1292 -0
  79. package/dist/cli/definitions-HF2FTHYU.js +32 -0
  80. package/dist/cli/doctorCommand-B7BPQMN6.js +76 -0
  81. package/dist/cli/edit-JHCPTQFT.js +28 -0
  82. package/dist/cli/editorCommands-UIF5YLUZ.js +33 -0
  83. package/dist/cli/encode-HAUZTYPT.js +17 -0
  84. package/dist/cli/frames-LSAUBZ7P.js +16 -0
  85. package/dist/cli/geo-4RNK3QVN.js +43 -0
  86. package/dist/cli/graphCommands-6BMAKGQE.js +184 -0
  87. package/dist/cli/graphFile-VPSQ6OF7.js +286 -0
  88. package/dist/cli/headlessCanvas-5XLDZT7M.js +15 -0
  89. package/dist/cli/helpCommand-3VRE3KVO.js +155 -0
  90. package/dist/cli/index.js +100 -30756
  91. package/dist/cli/math-ZRMLKU2D.js +16 -0
  92. package/dist/cli/mcp-ZLEEMYGF.js +164 -0
  93. package/dist/cli/parity-KINARCP2.js +328 -0
  94. package/dist/cli/pop-USDFXB7H.js +39 -0
  95. package/dist/cli/project-K3QIPGBB.js +12 -0
  96. package/dist/cli/projectDefinition-DMTZN2NE.js +27 -0
  97. package/dist/cli/projectRuntime-Z5PJOH47.js +48 -0
  98. package/dist/cli/registerStandardNodes-S2VLMF6J.js +3081 -0
  99. package/dist/cli/render-YURAPPUI.js +436 -0
  100. package/dist/cli/runCommand-PI764LEG.js +198 -0
  101. package/dist/cli/runner-RA6UKEPD.js +37 -0
  102. package/dist/cli/runtime/image.ts +277 -0
  103. package/dist/cli/runtime/stage.ts +4 -1
  104. package/dist/cli/stageRunner-KUNIMQKJ.js +10 -0
  105. package/dist/cli/verbs-RCE3K4VQ.js +19 -0
  106. package/dist/cli/webBuild-GT4PZT5D.js +37 -0
  107. package/dist/contracts/documentFormat.d.ts +18 -0
  108. package/dist/contracts/documentFormat.js +195 -0
  109. package/dist/contracts/editor.d.ts +17 -0
  110. package/dist/contracts/index.d.ts +1 -0
  111. package/dist/contracts/index.js +1 -0
  112. package/dist/image.d.ts +141 -0
  113. package/dist/image.js +127 -0
  114. package/dist/index.html +1 -1
  115. package/dist/player/editor.js +32 -7
  116. package/dist/runtime/builtins/headless.d.ts +19 -0
  117. package/dist/runtime/builtins/headless.js +25 -0
  118. package/dist/runtime/builtins/image/contactSheet.d.ts +226 -0
  119. package/dist/runtime/builtins/image/contactSheet.js +199 -0
  120. package/dist/runtime/builtins/image/index.d.ts +9 -0
  121. package/dist/runtime/builtins/image/index.js +9 -0
  122. package/dist/stage.js +4 -1
  123. package/doc/CLI_REFERENCE.md +73 -2
  124. package/doc/EDITOR_EXPORT.md +11 -2
  125. package/doc/MCP.md +17 -1
  126. package/doc/NODE_REFERENCE.md +142 -0
  127. package/doc/PROJECT_AUTHORING.md +127 -7
  128. package/package.json +16 -4
  129. package/dist/assets/ExportDialog-C7dVGua4.js +0 -358
  130. package/dist/assets/ExportDialog-DOq0flMV.css +0 -1
  131. package/dist/assets/geo-C2RHOVHC.js +0 -1
  132. package/dist/assets/math-DaDEgWKt.js +0 -1
  133. package/dist/assets/pop-pLH7L0PW.js +0 -1
package/AGENTS.md CHANGED
@@ -35,10 +35,12 @@ 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
39
 
40
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
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.
43
+
42
44
  `cascade build <graph.cascade> --out <new-directory>` exports a static browser
43
45
  player. Use repeatable `--asset <project-relative-file>` for inputs whose paths
44
46
  are computed in code. Read `doc/WEB_PLAYER.md` before exporting: server stages
@@ -219,6 +221,7 @@ type system knows what a `vec2` is; nothing tells it that `offset_x` and
219
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.
220
222
  - User modules are trusted project code, not a sandbox. Static definitions improve tooling and portability, not isolation.
221
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.
222
225
 
223
226
  ## Change workflow
224
227
 
@@ -228,9 +231,23 @@ the TypeScript 7 preview until it is stable and the repository gates pass.
228
231
  1. Add or update a focused regression test.
229
232
  2. Make the smallest change at the owning layer.
230
233
  3. Prefer deletion or an existing utility over another wrapper.
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.
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.
232
235
  5. For package/public API changes, also test the packed tarball from an empty temporary project.
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.
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/` |
234
251
 
235
252
  Do not add dependencies without a concrete need. Do not create extra packages unless they need independent publication or versioning.
236
253
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,193 @@
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
+
5
192
  ## 0.10.0 — 2026-10-12
6
193
 
7
194
  ### Added
package/README.md CHANGED
@@ -36,7 +36,7 @@ cascade . # reopen it later
36
36
  cascade run index.cascade --frames 1 --json # render headlessly
37
37
  ```
38
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.
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
40
 
41
41
  ## New in 0.9: shareable editors
42
42
 
@@ -383,7 +383,6 @@ a second set of node algorithms.
383
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. |
384
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. |
385
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). |
386
- | 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. |
387
386
  | External services | Project-owned and optional. Cascade itself requires no paid provider or model subscription. |
388
387
 
389
388
  ## Repository map