@field/cascade 0.3.1 → 0.4.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 +14 -9
- package/ARCHITECTURE.md +22 -6
- package/CHANGELOG.md +51 -1
- package/CONTRIBUTING.md +71 -0
- package/DESIGN.md +19 -13
- package/README.md +42 -11
- package/dist/assets/{CodeEditor-D22fVi-4.js → CodeEditor-BNOJIDzL.js} +4 -4
- package/dist/assets/{CodePanel-DPNEYfcR.js → CodePanel-2wp2G0Fj.js} +2 -2
- package/dist/assets/{CustomNodeDialog-DeHCAvgb.js → CustomNodeDialog-DNqaVBqA.js} +1 -1
- package/dist/assets/{ProjectSettings-DWpVtWEx.js → ProjectSettings-DcdYF2E1.js} +1 -1
- package/dist/assets/{SettingsDialog-za00IS3L.js → SettingsDialog-D2xVvyiR.js} +1 -1
- package/dist/assets/{VersionHistoryDialog-DTMGhI0_.js → VersionHistoryDialog-DW288ykF.js} +1 -1
- package/dist/assets/{core-JsyKMO1k.js → core-B1y38i95.js} +1 -1
- package/dist/assets/{cssMode-emdRheFK.js → cssMode-BLucnaln.js} +1 -1
- package/dist/assets/{editor.api-xHX-fMSo.js → editor.api-B3Et3Pph.js} +1 -1
- package/dist/assets/{freemarker2-C3M8_Gs3.js → freemarker2-DVlPoano.js} +1 -1
- package/dist/assets/geo-DhyFdBXX.js +1 -0
- package/dist/assets/{handlebars-CBMurtFk.js → handlebars-B5FZBAMR.js} +1 -1
- package/dist/assets/{html-xbLQwknw.js → html-FodD8KbR.js} +1 -1
- package/dist/assets/{htmlMode-2wKdDTon.js → htmlMode-CsG57VCD.js} +1 -1
- package/dist/assets/{image-i1j6nWKe.js → image-B3F-nq25.js} +1 -1
- package/dist/assets/index-CC6YQw2n.js +212 -0
- package/dist/assets/index-Y2ock1cw.css +1 -0
- package/dist/assets/{javascript-DJaOo_2I.js → javascript-B3gonF_H.js} +1 -1
- package/dist/assets/{jsonMode-Bheas8_0.js → jsonMode-Y3w1ahZg.js} +1 -1
- package/dist/assets/{liquid-BCj_BGbM.js → liquid-CTpWXIYO.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-BfIsx_xz.js → lspLanguageFeatures-CODBdKEZ.js} +1 -1
- package/dist/assets/{mdx-DwiQDiVO.js → mdx-CDAQJZIz.js} +1 -1
- package/dist/assets/{python-BjrB5nqj.js → python-LOIlxJU-.js} +1 -1
- package/dist/assets/{razor-CfoBmGDs.js → razor-CllPQSHo.js} +1 -1
- package/dist/assets/{tsMode-BcEoMSxp.js → tsMode-CO28ut8t.js} +1 -1
- package/dist/assets/{typescript-DIg7TEmQ.js → typescript-ruU9wKQ_.js} +1 -1
- package/dist/assets/{workers-vXYuwtPw.js → workers-Bc1Ywp4-.js} +1 -1
- package/dist/assets/{xml-DexLQIQy.js → xml-DoXP2Dh1.js} +1 -1
- package/dist/assets/{yaml-DUnD_1dE.js → yaml-D9YPyGiJ.js} +1 -1
- package/dist/cli/index.js +999 -185
- package/dist/cli/runtime/gpu.ts +71 -0
- package/dist/contracts/camera.d.ts +70 -0
- package/dist/contracts/camera.js +27 -0
- package/dist/contracts/capabilities.d.ts +6 -6
- package/dist/contracts/definition.d.ts +41 -2
- package/dist/contracts/index.d.ts +2 -0
- package/dist/contracts/index.js +2 -0
- package/dist/contracts/schema.js +25 -2
- package/dist/contracts/series.d.ts +75 -0
- package/dist/contracts/series.js +2 -0
- package/dist/contracts/validate.js +19 -3
- package/dist/contracts/values.d.ts +3 -2
- package/dist/contracts/values.js +1 -0
- package/dist/gpu.d.ts +17 -0
- package/dist/gpu.js +61 -1
- package/dist/index.html +2 -2
- package/dist/runtime/builtins/core/camera.d.ts +252 -0
- package/dist/runtime/builtins/core/camera.js +149 -0
- package/dist/runtime/builtins/core/index.d.ts +2 -1
- package/dist/runtime/builtins/core/index.js +3 -1
- package/dist/runtime/camera/index.d.ts +60 -0
- package/dist/runtime/camera/index.js +234 -0
- package/dist/runtime/definition/architecture.js +36 -1
- package/dist/runtime/gpu.d.ts +33 -0
- package/dist/runtime/gpu.js +218 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +3 -0
- package/dist/runtime/runtime.js +63 -6
- package/dist/runtime/series/index.d.ts +41 -0
- package/dist/runtime/series/index.js +167 -0
- package/dist/runtime/types.d.ts +1 -1
- package/doc/HEADLESS_GPU.md +160 -0
- package/doc/NODE_REFERENCE.md +36 -0
- package/doc/PROJECT_AUTHORING.md +106 -20
- package/package.json +10 -2
- package/dist/assets/geo-BAR6lQp5.js +0 -1
- package/dist/assets/index-BDV5xGBZ.css +0 -1
- package/dist/assets/index-CMcH8AgP.js +0 -212
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cascade agent guide
|
|
2
2
|
|
|
3
|
-
Cascade is a reusable generative-design graph runtime with an optional Studio UI. Keep authored algorithms independent from the editor so
|
|
3
|
+
Cascade is a reusable generative-design graph runtime with an optional Studio UI. Keep authored algorithms independent from the editor so a graph can run in Studio, on a server, or in a UI-free browser host when its declared execution locus and capabilities are supported.
|
|
4
4
|
|
|
5
5
|
## Start here
|
|
6
6
|
|
|
@@ -73,7 +73,7 @@ Project panels are trusted Studio extensions, not graph/runtime modules. Put the
|
|
|
73
73
|
|
|
74
74
|
## Create a deterministic node
|
|
75
75
|
|
|
76
|
-
Two node styles exist and both are
|
|
76
|
+
Two node styles exist and both are supported. A **definition-v1** module exports a literal `definition` and a typed `execute(context)`; it is statically inspectable and is what `cascade check` requires. A **dynamic** module exports `execute(node, graph)` and declares its ports and parameters imperatively inside it. Studio cooks both through `src/nodes/definition/projectDefinition.ts`. The CLI supports stills and frame sequences for fully deterministic graphs and for supported dynamic graphs, but rejects graphs mixing the two execution styles. Prefer definition-v1 for new nodes; inspect a project's current modules before assuming its style. Do not call dynamic modules "legacy" in user-facing guidance.
|
|
77
77
|
|
|
78
78
|
A definition-v1 module looks like this:
|
|
79
79
|
|
|
@@ -107,6 +107,9 @@ Definition rules:
|
|
|
107
107
|
and have the host registration select the executor. Never expose execution
|
|
108
108
|
location as an artist parameter; parity-test the shared contract.
|
|
109
109
|
- Declare every capability used. File, Python, and shell access are server-only; WebGL is browser-only.
|
|
110
|
+
- `context.nodeId` identifies the instance for namespaces such as `cachePath(context.nodeId, '.png')`; it does not grant access to siblings or hierarchy. A final output may instead have an artist-authored filename.
|
|
111
|
+
- Vector props support `min`, `max`, and `step`, shared across components. Props may declare a default `expression`; an explicitly saved value overrides that default, including when it equals the numeric default.
|
|
112
|
+
- WebGPU nodes declare `gpu` and use its shared device and per-node `cache`. Portable GPU nodes can run through optional Dawn in the CLI; browser-only declarations remain refused. Import constants and explicit `readTexture` (RGBA8 only) from `cascade/gpu`. Graph texture exchange remains future work. See `doc/HEADLESS_GPU.md` for bounded agent renders, diagnostics and hardware tests.
|
|
110
113
|
- Treat graph wires as the primary data boundary. A node may observe only its connected inputs, its props, and declared host capabilities; it must not inspect sibling nodes or the graph to discover data.
|
|
111
114
|
- Deterministic node modules may not retain module-level mutable values, access ambient state such as `globalThis`, browser storage, or `process`, run top-level effects, or import sibling node implementations. `cascade check` reports these as `architecture/*` diagnostics.
|
|
112
115
|
- A cache may memoize computation from wired inputs, but it must never supply unwired data. Make cache use an explicitly labelled prop and keep cache keys derived from the complete wired input and relevant props.
|
|
@@ -124,6 +127,7 @@ Use the runtime-native core vocabulary before creating a project wrapper:
|
|
|
124
127
|
- `cascade.core.Null` passes any value through unchanged so downstream wiring can remain stable while upstream branches are reorganized.
|
|
125
128
|
- `cascade.core.Random` maps explicit integer `seed` and `sample` inputs to a stable float in `[0, 1)`.
|
|
126
129
|
- `cascade.core.Remap` maps scalar ranges and optionally clamps via its `clamp` prop.
|
|
130
|
+
- `cascade.core.Camera` emits the one `camera` type, following Houdini's `/obj/cam`: `translate` and `rotate` (degrees, XYZ) with an optional `lookat`, and a lens given as `focal` and `aperture` in millimetres rather than as a field of view. A camera looks down its own **-Z** with **+Y** up. `resolution` is on the camera because Houdini derives the vertical aperture from the frame shape, and it is one `vec2i` rather than Houdini's `resx`/`resy` because the vec rule below is the more specific one. Every derivation — the basis, the view and projection matrices, the horizontal and vertical angles — lives in `packages/runtime/src/camera`; never derive them a second time in a renderer.
|
|
127
131
|
|
|
128
132
|
The geometry set is reserved the same way, under `cascade.geo.*`:
|
|
129
133
|
`Rectangle`, `Circle`, `Transform`, `Merge`, `CopyToPoints`, and `SvgExport`.
|
|
@@ -146,13 +150,13 @@ type system knows what a `vec2` is; nothing tells it that `offset_x` and
|
|
|
146
150
|
|
|
147
151
|
## Animation, expressions, and parameters
|
|
148
152
|
|
|
149
|
-
- **`
|
|
153
|
+
- **`resolvePropBinding` in `packages/runtime/src/params/resolve.ts` owns binding precedence:** channel, expression, value. Studio's `Node.evalParm` and the neutral runtime both call it with their own expression scope and frame. Never read `prop.value` to obtain an animated parameter or implement a second precedence rule.
|
|
150
154
|
- **A parameter is one store.** `param()` declares the parameter; the value, the expression and the channel live in the prop of the same name. `NodeParameter.value` reads *resolved*; `rawParameterValue()` reads what the author typed, and is what serialization and cache keys must use. `param()` is re-declared on every cook of a dynamic node, so it must stay idempotent — it may never reset a value, an expression, or a channel.
|
|
151
155
|
- **Mechanisms belong to the runtime, composition to the host.** `packages/runtime/src/expressions` owns preprocessing, scope and the maths library; `packages/runtime/src/animation` owns the channel model, sampling, interpolation, serialization and frame-range walking. Both depend only on contracts. Do not implement interpolation, a frame clock, or a second `$T` anywhere else.
|
|
152
156
|
- **The serialized shape is owned by contracts** (`packages/contracts/src/animation.ts`): a channel is `{ keys: [{ frame, value, interpolation? }] }` inside the node's `props`, with `interpolation` omitted when it is the `smooth` default. There is no timeline section in the document, and adding one would need reconciling on every rename, delete and embed.
|
|
153
157
|
- Bare trigonometry is **radians**, deliberately unlike Houdini; `sind`/`cosd`/`tand`/`radians()`/`degrees()` exist for formulae carried over. Only `ch()`, `chs()` and `chv()` are scanned for dependencies, so a new way to reach another parameter also needs a dependency pattern or it will not recook.
|
|
154
|
-
- The deterministic runtime
|
|
155
|
-
- Studio's timeline
|
|
158
|
+
- The deterministic runtime resolves parameter animation through `setFrame`, `setFps`, and `run({ frame, fps })`. `cascade run --frames` supports fully definition-v1 graphs when the Node host can supply their capabilities. A browser-only node still cannot run in that host.
|
|
159
|
+
- Studio's timeline supplies the playhead and fps to the engine; its range and loop setting are panel state. Parameter channels are saved in the document, but playback settings are not.
|
|
156
160
|
|
|
157
161
|
## Agent sessions
|
|
158
162
|
|
|
@@ -178,7 +182,7 @@ type system knows what a `vec2` is; nothing tells it that `offset_x` and
|
|
|
178
182
|
- Contracts have no runtime dependencies.
|
|
179
183
|
- Runtime depends only on contracts and contains no DOM, Svelte, Express, Node filesystem, or child-process imports.
|
|
180
184
|
- Hosts inject capabilities explicitly.
|
|
181
|
-
- Studio
|
|
185
|
+
- 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.
|
|
182
186
|
- User modules are trusted project code, not a sandbox. Static definitions improve tooling and portability, not isolation.
|
|
183
187
|
- Keep legacy support inside the existing Studio/CLI compatibility engine; do not spread compatibility branches into the deterministic runtime.
|
|
184
188
|
|
|
@@ -198,9 +202,10 @@ Do not add dependencies without a concrete need. Do not create extra packages un
|
|
|
198
202
|
|
|
199
203
|
## Versioning
|
|
200
204
|
|
|
201
|
-
Cascade `0.2.0` is the 2026 architecture rework
|
|
202
|
-
|
|
203
|
-
|
|
205
|
+
Cascade `0.2.0` is the 2026 architecture rework; `0.3.0` added animation and the
|
|
206
|
+
agent console. Read `package.json` for the checkout version and `CHANGELOG.md`
|
|
207
|
+
for release history and unreleased changes; a local build can contain changes
|
|
208
|
+
not yet in the published package. Update the changelog before a release commit. Increment the
|
|
204
209
|
root package and CLI patch version for every committed feature or release
|
|
205
210
|
change, keeping `package.json`, the lockfile, and CLI output aligned. A minor
|
|
206
211
|
bump is for a feature large enough to need its own `CHANGELOG.md` section.
|
package/ARCHITECTURE.md
CHANGED
|
@@ -30,8 +30,8 @@ Randomness is a pure function of an authored seed, never ambient process state.
|
|
|
30
30
|
|
|
31
31
|
Hosts adapt the neutral runtime to an environment:
|
|
32
32
|
|
|
33
|
-
- Node: files, assets, media, Python, and
|
|
34
|
-
- Browser: assets, media, and
|
|
33
|
+
- Node: files, assets, media, Python, shell, and optional Dawn WebGPU in the CLI.
|
|
34
|
+
- Browser: assets, media, and the `gpu` capability when WebGPU is available.
|
|
35
35
|
- Mixed application: an explicit bridge for serializable server stages.
|
|
36
36
|
|
|
37
37
|
Capabilities are injected. A node’s literal `runsOn` and `capabilities` fields are checked before its `execute` module is loaded.
|
|
@@ -44,11 +44,19 @@ resize, composite, and encode when both Canvas/WebGL and native implementations
|
|
|
44
44
|
exist. Both executors must obey the same definition and should share golden
|
|
45
45
|
parity tests for geometry, metadata, and edge cases.
|
|
46
46
|
|
|
47
|
+
`packages/runtime/src/gpu.ts` owns shared device/cache lifecycle with an injected
|
|
48
|
+
acquisition function. Studio acquires browser WebGPU; `src/cli/headlessGpu.ts`
|
|
49
|
+
loads optional Dawn lazily. The runtime awaits readiness and supplies a per-node
|
|
50
|
+
view; the application owns disposal. `cascade/gpu` supplies explicit RGBA8
|
|
51
|
+
readback without encoding or colour conversion. Graph ports still exchange
|
|
52
|
+
images; GPU-resident intermediate connections remain future work. See
|
|
53
|
+
[headless GPU rendering](doc/HEADLESS_GPU.md).
|
|
54
|
+
|
|
47
55
|
`server/` is the project-scoped Node application host. It owns project paths, compilation, HTTP transport, media serving, Python workers, shell policy, and credentials. It is separately manifested and is not a third contracts/runtime workspace.
|
|
48
56
|
|
|
49
57
|
## Applications and controllers
|
|
50
58
|
|
|
51
|
-
Studio’s Svelte components under `src/editor` own rendering, selection, panels, and interaction state. Its compatibility graph now has one graph-owned cook scheduler, while `StudioGraphController` centralizes an increasing set of structural mutations and publishes view snapshots. Compatibility adapters still present runtime-owned built-ins in Studio; collapse/extract and the remaining
|
|
59
|
+
Studio’s Svelte components under `src/editor` own rendering, selection, panels, and interaction state. Its compatibility graph now has one graph-owned cook scheduler, while `StudioGraphController` centralizes an increasing set of structural mutations and publishes view snapshots. Compatibility adapters still present runtime-owned built-ins in Studio; collapse/extract and the remaining dynamic compatibility nodes must migrate before Studio can consume `packages/runtime` directly.
|
|
52
60
|
|
|
53
61
|
Studio uses Dockview through the public `dockview` API. Code panels lazy-load
|
|
54
62
|
Monaco and its native editor/TypeScript workers rather than adding Monaco to the
|
|
@@ -115,13 +123,13 @@ Execution failures resolve to a failed `RunResult`; API misuse and invalid prefl
|
|
|
115
123
|
|
|
116
124
|
## Animation
|
|
117
125
|
|
|
118
|
-
A parameter carries up to three bindings: a raw value, an expression, and a keyframe channel.
|
|
126
|
+
A parameter carries up to three bindings: a raw value, an expression, and a keyframe channel. `packages/runtime/src/params/resolve.ts` owns their shared resolution rule: channel, expression, value. A channel that samples takes precedence and leaves the expression stored but inert, so emptying the channel restores it. Studio invokes the resolver from `Node.evalParm`; the deterministic runtime invokes it through `PropAnimator`. Nothing else in Studio may read a prop's `value` directly to obtain an animated parameter; a second rule is how an expression badge and a viewer disagree about the same frame.
|
|
119
127
|
|
|
120
|
-
The mechanisms are runtime-owned and the composition is
|
|
128
|
+
The mechanisms are runtime-owned and the composition is host-specific. `packages/runtime/src/expressions` owns preprocessing (`$F`, `$FF`, `$T`, `$FPS` rewritten to plain identifiers), the evaluation scope, and the maths library; `packages/runtime/src/animation` owns the channel model, sampling, interpolation, serialization, and frame-range walking; `packages/runtime/src/params` owns binding resolution and deterministic graph-wide animation. These modules depend only on contracts or other runtime modules. Studio supplies its compatibility graph scope, while `PropAnimator` supplies the neutral runtime scope, including lazy `ch()` dependency resolution.
|
|
121
129
|
|
|
122
130
|
`packages/contracts/src/animation.ts` owns the serialized shape. A channel lives inside the node's `props`, not in a separate timeline object, because a parameter's animation belongs to the parameter; a document with a timeline section would need reconciling every time a node was renamed, deleted, or embedded.
|
|
123
131
|
|
|
124
|
-
The deterministic runtime has
|
|
132
|
+
The deterministic runtime has parameter animation and an explicit graph clock. `setFrame(frame)` and `setFps(fps)` re-resolve bound props without cooking, so inspection can scrub deterministically. `run({ frame, fps })` resolves every bound prop before node execution; the same graph at the same authored state, frame, and fps receives the same parameter values. `cascade run --frames` uses this path for definition-v1 graphs and passes each requested frame and fps into the run. The runtime never reads wall-clock time.
|
|
125
133
|
|
|
126
134
|
## Agent sessions
|
|
127
135
|
|
|
@@ -139,6 +147,14 @@ Document freshness is a watcher, not a poll of the agent. `server/src/graphWatch
|
|
|
139
147
|
|
|
140
148
|
Project node modules are trusted code. Capabilities describe support and portability; they are not a sandbox.
|
|
141
149
|
|
|
150
|
+
Studio binds to loopback by default. Remote access requires a specific
|
|
151
|
+
hostname or private interface address via `--host`; wildcard remote binds are
|
|
152
|
+
rejected. That non-loopback host becomes the default trusted browser hostname,
|
|
153
|
+
and repeatable `--trusted-host` values add exact browser authorities when the
|
|
154
|
+
bind address and public hostname differ, including a reverse proxy to a
|
|
155
|
+
loopback bind. Every reachable peer on that trusted interface can access the
|
|
156
|
+
project APIs, so this mode is intended for an authenticated VPN or trusted LAN.
|
|
157
|
+
|
|
142
158
|
All project HTTP APIs require an exact allowed Host. Origin is validated when
|
|
143
159
|
present and hostile or null Origins are rejected; same-origin GETs may omit it.
|
|
144
160
|
Filesystem resolution checks lexical paths and canonical existing targets or
|
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to Cascade. Newest first.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 0.4.0 — 2026-09-09
|
|
6
|
+
|
|
7
|
+
### Documentation
|
|
8
|
+
|
|
9
|
+
- Updated current guides and generated project instructions for definition-v1
|
|
10
|
+
animation, stored `props`, instance identity, vector metadata, and the shared
|
|
11
|
+
GPU capability. Clarified host requirements, Studio's remaining runtime
|
|
12
|
+
migration, export limitations, and the distinction between implemented
|
|
13
|
+
workflows and future product directions.
|
|
14
|
+
|
|
15
|
+
### Animation
|
|
16
|
+
|
|
17
|
+
- The deterministic runtime resolves expressions and keyframe channels at an
|
|
18
|
+
explicit frame through the shared parameter resolver. `cascade run --frames`
|
|
19
|
+
can render fully definition-v1 graphs with compatible Node-host capabilities;
|
|
20
|
+
mixed definition-v1/dynamic graphs remain unsupported by the CLI.
|
|
6
21
|
|
|
7
22
|
### Node authoring
|
|
8
23
|
|
|
@@ -27,6 +42,41 @@ Notable changes to Cascade. Newest first.
|
|
|
27
42
|
|
|
28
43
|
- **The CLI build resolves `@cascade/runtime/params`.** `src/nodes/Node.ts` imports `resolvePropBinding` from it, the browser build resolved it through `vite.config.ts`, and the CLI build had no alias — so the CLI, which is what the sketches actually run, was the broken half.
|
|
29
44
|
|
|
45
|
+
### Camera
|
|
46
|
+
|
|
47
|
+
- **A camera is a core type, and it is Houdini's camera.** `camera` joins `CORE_TYPES`, `cascade.core.Camera` emits one, and every derivation — basis, view and projection matrices, horizontal and vertical angle — lives in `cascade/runtime/camera` so no renderer derives it twice. Following `/obj/cam` costs the two things the obvious design would have done instead: there is **no field of view** (`focal` and `aperture` in millimetres, angle derived — Houdini's 50 mm on 41.4214 mm is exactly 45°), and the orientation is **`translate` and `rotate`** rather than eye-and-target, looking down its own **-Z** with **+Y** up, with look-at layered on top as an override. `resolution` is on the camera because Houdini derives the vertical aperture from the frame shape; it is one `vec2i` rather than `resx`/`resy` because the vec rule is the more specific one. Matching a frame is therefore always one number, never two.
|
|
48
|
+
- `rotate.z` is a roll about the camera's own view direction. The first two rotation orders tried were indistinguishable from this one by every test in the suite — with `rotate.z` at zero all three agree exactly — so the test that separates them asserts that roll changes the up and leaves the view direction alone.
|
|
49
|
+
|
|
50
|
+
### Series
|
|
51
|
+
|
|
52
|
+
- **A series is a graph plus an ordered list of parameter sets** (`CascadeSeries`, `runSeries`), cooked once per set and addressed by **record id, never index**, because a filter change reorders a set and a judgement pinned to a position silently becomes a different picture. `CascadePreset` and `applyPreset` already were the parameter set and had no callers. There is no marked region: the affected subgraph is derived from the overrides, so nothing can be marked wrongly.
|
|
53
|
+
- A parameter set is **sparse**, so every instance cooks from a baseline captured before the first `applyPreset` — otherwise an instance that overrides nothing inherits the previous one's values, which is accidental feedback in a mechanism specified as having none, and it presents as a flaky renderer rather than as a bug. `first` reorders the work and never the results, so a gallery fills in as instances land without the list reshuffling under a selection.
|
|
54
|
+
|
|
55
|
+
### Capabilities
|
|
56
|
+
|
|
57
|
+
- **Studio can reach the shell.** The server has had an allowlist-gated `/api/shell` for a while and Studio never wired it as a node capability, so a definition declaring `capabilities: ['shell']` ran through `cascade run` and threw in the browser — a node marked `runsOn: 'portable'` that runs in one host is what `runsOn` exists to prevent. A `CascadeAbortSignal` is bridged to a DOM one rather than serialised; a 403 re-handshakes exactly once and then reports, naming the Allowed Commands editor rather than a status code.
|
|
58
|
+
|
|
59
|
+
### Correctness
|
|
60
|
+
|
|
61
|
+
- **A `vec3` prop stays a `vec3`.** `isColorValue` answers true for any three- or four-number array and the deserialise path had no `type === 'color'` guard, so every vector prop in every sketch was rewritten on load — `[0.55, 0.12, 1.95]` reached `execute` as a colour object, coerced and divided by 255. A guard existed one branch away and never ran, because a **project** module's definition arrives asynchronously and `node.parameters` is empty at load. Coercion is now decided by ambiguity: objects and strings still normalise, arrays only where the prop is already declared a colour.
|
|
62
|
+
- **An error in the log says what it is.** The Log panel `JSON.stringify`s any object and `Error.message` is non-enumerable, so a `TypeError` and a `GPUPipelineError` were equally invisible as `{}`.
|
|
63
|
+
- **Selecting a failing node no longer cooks it forever.** The Viewer's rAF pump is throttled to 100 ms and polls its watched node while dirty; an execute that throws never reaches `clean`, so it ran a full `scheduler.flush()` ten times a second, re-fetching inputs over the network, at 61 fps and never looking wrong. `Node.hasSettledFailure` is what the poll now skips — deliberately not folded into `isDirty`, because an explicit `requestOutput` still retries and that is the transient GPU and network case.
|
|
64
|
+
- **Renaming a node is a double click.** The name label sits in the middle of the node body and a single click opened the rename editor, so aiming at a node to select it renamed it instead, in memory only and discarded on reload.
|
|
65
|
+
- **A proxied Studio can save.** `https` origins are accepted and default ports matched, so a reverse-proxied or Tailscale-served Studio can POST — which is also what unblocks WebGPU, the clipboard and the microphone, all of which need a secure context.
|
|
66
|
+
|
|
67
|
+
### Headless GPU
|
|
68
|
+
|
|
69
|
+
- Optional pinned Dawn (`webgpu@0.6.0`) in the CLI, loaded only for GPU execution.
|
|
70
|
+
Browser and Node hosts reuse shared device/cache lifecycle; portable and server
|
|
71
|
+
definitions may declare `gpu`. Browser-only nodes remain browser-only.
|
|
72
|
+
- Explicit `cascade/gpu` RGBA8 texture readback, with padded-row removal and
|
|
73
|
+
cancellation cleanup. Graph texture transport remains outside this stage.
|
|
74
|
+
- `run --frames ... --json` returns an image manifest and adapter metadata;
|
|
75
|
+
`--timeout <ms>` runs a supervised render process for agent/test callers.
|
|
76
|
+
Dedicated opt-in hardware and packed-package gates exercise real GPU output.
|
|
77
|
+
- Documented the decision, local/unreleased status, CLI manifest contract,
|
|
78
|
+
verification evidence and platform limits in [Headless GPU](doc/HEADLESS_GPU.md).
|
|
79
|
+
|
|
30
80
|
## 0.3.1
|
|
31
81
|
|
|
32
82
|
### Fixed
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Contributing to Cascade
|
|
2
|
+
|
|
3
|
+
Cascade is a free, MIT-licensed creative graph platform. Contributions can be
|
|
4
|
+
bug reports, reproducible sketches, documentation, tests, or code. Core
|
|
5
|
+
development does not require an AI provider or a paid service account.
|
|
6
|
+
|
|
7
|
+
## Find the owning layer
|
|
8
|
+
|
|
9
|
+
Read [AGENTS.md](AGENTS.md) for repository conventions, [DESIGN.md](DESIGN.md)
|
|
10
|
+
for product decisions, and [ARCHITECTURE.md](ARCHITECTURE.md) for dependencies.
|
|
11
|
+
|
|
12
|
+
- `packages/contracts/` owns public types and serialized formats.
|
|
13
|
+
- `packages/runtime/` owns environment-neutral execution mechanisms.
|
|
14
|
+
- `server/` owns project files, compilation, processes, and host transports.
|
|
15
|
+
- `src/editor/` owns Studio interactions and presentation.
|
|
16
|
+
- Sketch repositories own creative algorithms, providers, and project panels.
|
|
17
|
+
|
|
18
|
+
Keep provider SDKs and client-specific data in projects. Do not add dependencies
|
|
19
|
+
or packages without a demonstrated need and an agreed scope.
|
|
20
|
+
|
|
21
|
+
## Develop and verify
|
|
22
|
+
|
|
23
|
+
Use Node.js 22.13 or newer. Install dependencies with `npm install`; the core
|
|
24
|
+
uses TypeScript 6. `npm run dev` starts the Studio development frontend.
|
|
25
|
+
Project-host workflows are exercised through a built CLI and a project folder.
|
|
26
|
+
|
|
27
|
+
Add a focused regression test for a behavior change, make the smallest change
|
|
28
|
+
at the owning layer, and run that test first. Use the applicable repository gates:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm run check
|
|
32
|
+
npm run test:run
|
|
33
|
+
npm --prefix server run build
|
|
34
|
+
npm run build
|
|
35
|
+
npm run build:cli
|
|
36
|
+
git diff --check
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`npm run build` also runs `build:cli` through its postbuild hook. Keep a final
|
|
40
|
+
CLI build after any separate Vite build because Vite refreshes `dist/`. Coordinate
|
|
41
|
+
rebuilds when running Studio servers serve from that checkout.
|
|
42
|
+
|
|
43
|
+
For public API or packaging changes, run `npm run test:package`, which exercises
|
|
44
|
+
the packed distribution from a temporary consumer. Built-in node-definition or
|
|
45
|
+
registry changes also require `npm run build:node-reference`; include its result.
|
|
46
|
+
|
|
47
|
+
For prose-only changes, verify source claims, links, examples, and diff hygiene.
|
|
48
|
+
When changing generated project instructions in `server/src/projectTemplate.ts`,
|
|
49
|
+
also run `npx --no-install vitest run tests/project-template.test.ts`.
|
|
50
|
+
|
|
51
|
+
## Report useful evidence
|
|
52
|
+
|
|
53
|
+
A bug report should identify the Cascade version and whether it is a published
|
|
54
|
+
package or local checkout, the host/browser and relevant GPU, the smallest
|
|
55
|
+
reproducing graph, and expected versus observed output. Include safe fixtures
|
|
56
|
+
instead of credentials or private client data. A static check passing is not
|
|
57
|
+
proof that a graph rendered successfully.
|
|
58
|
+
|
|
59
|
+
For visual changes, preserve the inputs, seed, frame/fps, dimensions, and code
|
|
60
|
+
revision used for comparison. Compare decoded pixels or geometry where useful;
|
|
61
|
+
file size and image-wide averages do not establish visual equivalence.
|
|
62
|
+
|
|
63
|
+
## Documentation and releases
|
|
64
|
+
|
|
65
|
+
Update current instructions alongside behavior changes. Keep historical notes
|
|
66
|
+
dated and mark proposals as unimplemented. Update the root
|
|
67
|
+
[CHANGELOG.md](CHANGELOG.md); `spec/CHANGELOG.md` preserves earlier history.
|
|
68
|
+
Never edit the generated [node reference](doc/NODE_REFERENCE.md) by hand.
|
|
69
|
+
|
|
70
|
+
Release/version rules live in [AGENTS.md](AGENTS.md). Publishing and deployment
|
|
71
|
+
are separate maintainer actions; a documentation update does not publish a release.
|
package/DESIGN.md
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
## Source of truth
|
|
4
4
|
|
|
5
5
|
- Status: Active
|
|
6
|
-
- Last refreshed: 2026-09-08 (0.3.
|
|
6
|
+
- Last refreshed: 2026-09-08 (0.3.1)
|
|
7
7
|
- Primary product surfaces: reusable graph runtime, optional Studio workbench, headless Node/browser hosts, Inspector, Viewer, Timeline, agent console, node ports, project-defined workbenches
|
|
8
|
-
- Evidence reviewed: `VISION.md`, `ARCHITECTURE.md`, `CHANGELOG.md`, `spec/CASCADE_SUBNET_AND_SHELL_SPEC.md`, `src/types/coreTypes.ts`, `src/editor/Inspector.svelte`, `src/editor/Viewer.svelte`, `src/editor/panels/TimelinePanel.svelte`, `src/editor/panels/AgentPanel.svelte`, `src/editor/components/PortEditor.svelte`, `src/editor/components/typeRenderers.ts`, `packages/runtime/src/expressions/`, `packages/runtime/src/animation/`, `server/src/agent/`, and
|
|
8
|
+
- Evidence reviewed: `VISION.md`, `ARCHITECTURE.md`, `CHANGELOG.md`, `spec/CASCADE_SUBNET_AND_SHELL_SPEC.md`, `src/types/coreTypes.ts`, `src/editor/Inspector.svelte`, `src/editor/Viewer.svelte`, `src/editor/panels/TimelinePanel.svelte`, `src/editor/panels/AgentPanel.svelte`, `src/editor/components/PortEditor.svelte`, `src/editor/components/typeRenderers.ts`, `src/nodes/definition/gpuCapability.ts`, `packages/runtime/src/runtime.ts`, `packages/runtime/src/params/`, `packages/runtime/src/expressions/`, `packages/runtime/src/animation/`, `server/src/agent/`, `server/src/security.ts`, and `server/src/cliCommands.ts`
|
|
9
|
+
|
|
10
|
+
This document contains both current product rules and intended direction. Sections labelled **Current** describe implemented behavior in the repository. Sections labelled **Target** or **Planned** describe design direction and are not a release commitment. Open questions remain undecided until accepted in a specification or implementation plan.
|
|
9
11
|
|
|
10
12
|
## Brand
|
|
11
13
|
|
|
@@ -35,16 +37,16 @@
|
|
|
35
37
|
|
|
36
38
|
- One type, one presentation contract: the same type vocabulary drives ports, Inspector, and Viewer.
|
|
37
39
|
- Progressive disclosure: compact summaries in dense panels; richer previews and metadata in Viewer; raw JSON only on demand.
|
|
38
|
-
- Edit only what can be authored honestly: inputs may edit portable values; connected inputs and outputs are read-only
|
|
39
|
-
- Expensive context changes stay explicit:
|
|
40
|
+
- Edit only what can be authored honestly: inputs may edit portable values; connected inputs and outputs are read-only. Future live GPU texture values should be inspected rather than fabricated through form fields.
|
|
41
|
+
- Expensive context changes stay explicit: server materialization, file writes and GPU readback are requested operations, never invisible UI coercions. Graph texture connections remain future work.
|
|
40
42
|
- Project types extend by registration, not central switch statements.
|
|
41
43
|
- The graph runtime is a product surface independent from Studio. Headless hosts consume it now; Studio's compatibility graph has one scheduler/controller boundary but still requires a deliberate built-in and structural-command migration before it consumes the neutral runtime directly.
|
|
42
44
|
- Node metadata is deterministic. A literal exported definition declares ports, properties, types, execution locus, and capabilities; `execute` performs computation only.
|
|
43
|
-
- A parameter is one store with three bindings. A value, an expression, and a keyframe channel live on the same parameter and
|
|
45
|
+
- A parameter is one store with three bindings. A value, an expression, and a keyframe channel live on the same parameter and use the shared `resolvePropBinding` rule in a fixed order: channel, then expression, then value. Studio calls that rule from `Node.evalParm`; the neutral runtime calls it through `PropAnimator`. Two stores is what 0.3.0 removed — `param()` wrote to one and every binding read the other, so no parameter a sketch actually declared could carry an expression or a key, and nothing errored. A stronger binding hides a weaker one rather than destroying it, so emptying a channel returns the expression that was already there.
|
|
44
46
|
- Time is an expression, not a node. A parameter holding `sin($T) * 40` is the whole of an oscillator, which is why there is no oscillator node and why portable nodes still must not read ambient time or randomness themselves. The variables and the function names are Houdini's, because the people this is for already have them in their hands; the one deliberate divergence is that bare trigonometry is in radians, with `sind`/`cosd`/`tand` provided for formulae carried across.
|
|
45
47
|
- An agent run belongs to the server, not to the browser looking at it. Closing a tab detaches a reader; the transcript is buffered with sequence numbers so reopening replays what was missed and says how much it dropped. The alternative — a run owned by an HTTP request — kills the agent mid-edit on a reload, which is what 0.3.0 fixed.
|
|
46
48
|
- Rendering offline stops at a numbered image sequence. Handing frames to an encoder is a separate decision with its own dependency, and a directory of frames is the input every encoder already takes.
|
|
47
|
-
- Hosts provide explicit capabilities. File, Python, media,
|
|
49
|
+
- Hosts provide explicit capabilities. File, Python, media, GPU, and shell access are never ambient runtime assumptions. Provider-specific AI abstractions belong to projects or embedding hosts, not Cascade core.
|
|
48
50
|
- Neutral-runtime graph loads are atomic. Compatibility Studio collapse/extract are a known migration gap and must move behind transactional structural commands before that guarantee applies to every editor operation.
|
|
49
51
|
- Tradeoff: geometry editors favor transparent structured editing and previews over specialized CAD interactions in this pass.
|
|
50
52
|
|
|
@@ -53,9 +55,10 @@
|
|
|
53
55
|
- `@cascade/contracts` is the dependency-free source of truth for graph documents, core and namespaced types, deterministic node definitions, diagnostics, run results, capabilities, and schemas.
|
|
54
56
|
- `@cascade/runtime` is the deterministic environment-neutral graph loader, validator, scheduler, serializer, trigger engine, and hierarchy implementation. It depends only on contracts; dynamic compatibility remains in Studio/CLI during migration.
|
|
55
57
|
- The root `cascade` package is the sole published distribution and CLI owner. It exposes `cascade/contracts`, `cascade/contracts/schema`, `cascade/runtime`, `cascade/runtime/node`, `cascade/runtime/browser`, `cascade/runtime/expressions`, `cascade/runtime/animation`, `cascade/runtime/definition/extract`, `cascade/io`, `cascade/net`, `cascade/stage`, and the compatibility `cascade/shell` entry point.
|
|
56
|
-
- Node and browser hosts inject only the capabilities they support.
|
|
58
|
+
- Node and browser hosts inject only the capabilities they support. GPU can be supplied by browser WebGPU or optional Dawn; file, Python and shell remain server-only. A portable declaration still requires compatible capabilities.
|
|
57
59
|
- The Studio owns canvas/view classes and a single `StudioGraphController`; its compatibility `Graph`/`Node` engine is still being reduced. Custom frontends and backend services use the neutral runtime directly and do not load editor code.
|
|
58
|
-
- **
|
|
60
|
+
- **Current GPU stage:** Studio and the optional Dawn CLI host share device/cache lifecycle through the neutral runtime. Each declaring node gets a cache namespace. Explicit RGBA8 readback supports image export in either host; graph ports still exchange images. GPU-resident intermediate connections remain a later stage.
|
|
61
|
+
- **Web technology is the default renderer, and Python is the exception.** Canvas 2D, WebGL and WebGPU first; reach for a Python stage for libraries or tools that cannot reasonably run in the browser. Marcus's ruling, 2026-09-07: *"Cascade should prefer web tech canvas/webgpu to keep things smooth and fast. only use Python for exotic ML libraries and similar things that can't be easily pushed to the browser."* The reason is interaction: process startup, transport, and serialization can dominate a cook. Persistent workers avoid repeated process/model startup, but still have transfer costs. Existing project Python renderers need deliberate parity-tested migrations; this direction does not mean those implementations are already gone.
|
|
59
62
|
- Python interoperability remains a host capability for exotic libraries and compute stages. Exchange values cross explicit typed node boundaries rather than leaking Python process details into the neutral runtime.
|
|
60
63
|
- Internal packages remain two workspaces until independent versioning or external consumption justifies separate publication. More npm packages are not a goal by themselves.
|
|
61
64
|
|
|
@@ -72,8 +75,9 @@
|
|
|
72
75
|
|
|
73
76
|
## Headless and deployment model
|
|
74
77
|
|
|
75
|
-
- `createRuntime()` is the common entry point for
|
|
78
|
+
- `createRuntime()` is the common entry point for deterministic Node services, UI-free browser embeds, tests, and custom frontends. Studio still runs through its compatibility `Graph`/`Node` engine and controller while that migration continues.
|
|
76
79
|
- Registration is sealed after the first graph load. A loaded graph supports inspect, input/property/preset mutation, trigger, run, cancel, subscription, output retrieval, and disposal without editor dependencies.
|
|
80
|
+
- A loaded deterministic graph owns an explicit caller-controlled clock. `setFrame()` and `setFps()` re-resolve animated props for inspection without cooking; `run({ frame, fps })` resolves the same bindings before execution. The runtime never reads ambient time.
|
|
77
81
|
- One run is active per graph; there is no hidden run queue. API misuse rejects, while graph execution resolves to an explicit success/failure/cancelled result.
|
|
78
82
|
- A graph may run wholly in a backend, wholly in a compatible browser, or across an explicitly designed bridge. The runtime never silently moves a stage between hosts.
|
|
79
83
|
- File loading/saving, format versioning, presets, project paths, and workspace conveniences belong to stable platform services around the neutral runtime, not to individual generative algorithms.
|
|
@@ -82,7 +86,7 @@
|
|
|
82
86
|
|
|
83
87
|
- User node modules are trusted project code, not a sandbox. Deterministic definitions and architecture checks prevent common hidden-state designs and improve inspection, tooling, and portability; hard isolation would additionally require a separate realm or worker per node instance.
|
|
84
88
|
- Shell is a server-only capability backed by one project-scoped service. Projects invoke configured aliases as a fixed executable plus argument array with `shell: false`; arbitrary executables, interpolation, unsafe working directories, dangerous request-time environment overrides, and unbounded output are rejected. The subprocess inherits the server environment before project and allowlisted request overrides are applied.
|
|
85
|
-
-
|
|
89
|
+
- Sensitive browser transport is enabled for loopback and for an explicitly configured exact trusted host. Every request passes exact Host validation and Origin validation when present; sensitive routes also require a process-lifetime random capability token, apply route-local request limits, and avoid logging tokens, paths, arguments, environment, stdin, stdout, or stderr. Remote Studio rejects wildcard binds and grants every peer that can reach the trusted private interface the same project access.
|
|
86
90
|
- Timeout, cancellation, and output limits terminate the full process tree and wait for closure before reporting completion.
|
|
87
91
|
|
|
88
92
|
## Agent workflow contract
|
|
@@ -102,12 +106,14 @@
|
|
|
102
106
|
|
|
103
107
|
## Components
|
|
104
108
|
|
|
105
|
-
-
|
|
106
|
-
-
|
|
109
|
+
- **Current:** `PortEditor`, `JsonTree`, `ColorPicker`, `CoreValue`, `StructuredValue`, Viewer image zoom/pan behavior, and the type renderer registry.
|
|
110
|
+
- **Planned:** a shared type-value presentation shell, structured JSON editing, richer image and asset inspection, geometry summaries/previews, a Viewer output list, and texture inspection after texture values exist.
|
|
107
111
|
- Variants and states: `compact`, `inspect`, `view`; editable/read-only; empty/loading/error/stale; connected source; truncated/expanded
|
|
108
112
|
- Token/component ownership: `coreTypes.ts` owns semantic type metadata; the presentation registry owns components; Inspector/Viewer only choose context and mode
|
|
109
113
|
|
|
110
|
-
###
|
|
114
|
+
### Target core type presentation contract
|
|
115
|
+
|
|
116
|
+
This table defines the intended presentation contract. Individual rows may be only partially implemented; it does not imply that texture ports or every specialized editor currently exists.
|
|
111
117
|
|
|
112
118
|
| Family | Inspector/editor | Viewer |
|
|
113
119
|
| --- | --- | --- |
|
package/README.md
CHANGED
|
@@ -8,14 +8,15 @@ Created by Marcus Wendt at [FIELD.IO](https://www.field.io).
|
|
|
8
8
|
|
|
9
9
|
- A typed, inspectable graph model with lazy execution and explicit triggers.
|
|
10
10
|
- Deterministic custom-node definitions that tools can inspect without running user code.
|
|
11
|
-
-
|
|
11
|
+
- An environment-neutral runtime for Node services and UI-free browser applications.
|
|
12
|
+
- A Studio compatibility controller that already presents deterministic definitions alongside dynamic project nodes while its graph engine migrates to the neutral runtime.
|
|
12
13
|
- Project-native `.cascade` files, assets, presets, and Git-backed version history.
|
|
13
14
|
- Nested subnets with persistent hierarchy.
|
|
14
15
|
- Expressions on parameters, with Houdini's variables and functions: `$F`, `$FF`, `$T`, `$FPS`, and `ch()` to read another parameter.
|
|
15
16
|
- Keyframe channels on parameters, edited through a timeline panel with transport, playhead, scrubbing, and a dope sheet.
|
|
16
17
|
- Offline rendering with `cascade run`, including `--frames 1-100` for a numbered image sequence, rasterised through Skia rather than a browser.
|
|
17
18
|
- A coding-agent console per project, running in the project directory, with a watcher that picks up the files it rewrites without a reload.
|
|
18
|
-
- Explicit browser and server capabilities for
|
|
19
|
+
- Explicit browser and server capabilities for WebGPU, files, media, Python, and allowlisted shell commands.
|
|
19
20
|
- A Svelte Studio with an infinite canvas, Inspector, Viewer, timeline, and project workbench.
|
|
20
21
|
|
|
21
22
|
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.
|
|
@@ -29,7 +30,9 @@ npm install -g @field/cascade
|
|
|
29
30
|
cascade --version
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
That installs the `cascade` command: `cascade new` scaffolds a project, `cascade <directory>` opens it in Studio, and `cascade run`
|
|
33
|
+
That installs the latest published release and the `cascade` command: `cascade new` scaffolds a project, `cascade <directory>` opens it in Studio, and `cascade run` executes a graph headlessly. A generated project records the published package under the local alias `cascade`, so imports such as `cascade/contracts` resolve to `@field/cascade`.
|
|
34
|
+
|
|
35
|
+
The repository checkout can be ahead of the published release, even with the same version number. Use the global install to scaffold projects, then use their npm scripts or `npx --no-install cascade` to select the project-local version. For checkout development, see [Contributing](CONTRIBUTING.md). When diagnosing a difference, record the installed version and whether it resolves to a local checkout; a version match alone does not prove the same code is installed.
|
|
33
36
|
|
|
34
37
|
Offline image rendering uses Skia through `@napi-rs/canvas`, an optional dependency of about 26 MB. It installs by default; if you skipped optional dependencies, add it yourself:
|
|
35
38
|
|
|
@@ -63,10 +66,15 @@ npm run build:cli
|
|
|
63
66
|
|
|
64
67
|
## Create a project
|
|
65
68
|
|
|
69
|
+
`cascade new` scaffolds a project and starts Studio. After stopping that first
|
|
70
|
+
server, install the project's dependencies before reopening it. The example
|
|
71
|
+
below assumes the default projects directory; `cascade projects` reports yours.
|
|
72
|
+
|
|
66
73
|
```bash
|
|
67
74
|
cascade new my-artwork
|
|
68
75
|
cd ~/Documents/Cascade/my-artwork
|
|
69
|
-
|
|
76
|
+
npm install
|
|
77
|
+
npx --no-install cascade .
|
|
70
78
|
```
|
|
71
79
|
|
|
72
80
|
Studio binds to loopback by default. To use a Cascade workstation over a
|
|
@@ -81,6 +89,18 @@ both the bind target and allowed browser hostname. Use repeatable
|
|
|
81
89
|
`--trusted-host` only when the bind address and browser hostname differ.
|
|
82
90
|
Wildcard remote binds, unknown options, and invalid ports fail immediately.
|
|
83
91
|
|
|
92
|
+
An HTTPS reverse proxy may terminate TLS and forward to a loopback Studio. In
|
|
93
|
+
that case, name both sides explicitly:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cascade . --host 127.0.0.1 --port 3030 --trusted-host cascade.example.internal
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The proxy must preserve the browser's exact `Host`. If the external URL uses a
|
|
100
|
+
non-default port, include it in `--trusted-host`. Use `--no-open` and open the
|
|
101
|
+
HTTPS URL yourself: automatic opening still uses an HTTP URL. This flag admits
|
|
102
|
+
the authority; it does not configure TLS or the proxy itself.
|
|
103
|
+
|
|
84
104
|
A project is an ordinary directory or Git repository:
|
|
85
105
|
|
|
86
106
|
```text
|
|
@@ -152,7 +172,7 @@ Frames are written as `<out>/<node id>.<frame>.<ext>`, zero-padded to at least f
|
|
|
152
172
|
|
|
153
173
|
Drawing offline goes through Skia rather than a browser. The optional `@napi-rs/canvas` supplies `OffscreenCanvas`, `Image`, `Path2D` and the rest as globals in the Node process, deliberately not `document`, since that is how a node detects its host. So a node that draws on an `OffscreenCanvas` needs no separate headless implementation, and the built-in `cascade.image.*` library rasterises through Skia in Node too, so a graph built from it renders headlessly with no browser involved. A run without the renderer installed still works for graphs that draw nothing, and says what is missing if a cook fails in a canvas-shaped way.
|
|
154
174
|
|
|
155
|
-
`--frames`
|
|
175
|
+
`--frames` works for an all-dynamic graph and for an all-definition-v1 graph. Definition-v1 runs resolve stored expressions and keyframe channels from the explicit `frame` and `fps` supplied to each deterministic run. A CLI graph that mixes the two node styles is rejected explicitly because there is not yet a bounded adapter between the execution engines.
|
|
156
176
|
|
|
157
177
|
## The agent console
|
|
158
178
|
|
|
@@ -219,7 +239,7 @@ host's executor, so the graph stays portable and contains no backend selector.
|
|
|
219
239
|
This is the intended pattern for media transforms such as crop or resize; use
|
|
220
240
|
shared parity tests to keep their outputs and metadata aligned.
|
|
221
241
|
|
|
222
|
-
There is a second node style, and it is not deprecated. A **dynamic** module exports `execute(node, graph)` and declares its ports and parameters imperatively inside it, as `node.param('size', 1024, { min: 16, max: 4096 })`, running once for discovery and again on every cook. Studio cooks both styles and a Studio graph may mix them
|
|
242
|
+
There is a second node style, and it is not deprecated. A **dynamic** module exports `execute(node, graph)` and declares its ports and parameters imperatively inside it, as `node.param('size', 1024, { min: 16, max: 4096 })`, running once for discovery and again on every cook. Studio cooks both styles and a Studio graph may mix them through its compatibility controller. The CLI uses the deterministic runtime for an all-definition-v1 document and the compatibility engine for an all-dynamic document; it rejects a mixed document. `cascade check` requires definition-v1 modules because it inspects them statically. A malformed definition never falls back to dynamic execution — it is reported. A project's own `AGENTS.md`, written by `cascade new`, states which style that project expects.
|
|
223
243
|
|
|
224
244
|
Provider integrations are project code, not Cascade infrastructure. A project
|
|
225
245
|
can call a remote service from a Studio/browser node, invoke Python or an
|
|
@@ -262,11 +282,22 @@ cancellation, event subscriptions, output retrieval, and disposal. Hosts
|
|
|
262
282
|
decide which capabilities exist; Cascade never silently moves a stage between
|
|
263
283
|
browser and server.
|
|
264
284
|
|
|
265
|
-
The same
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
second set of node algorithms.
|
|
285
|
+
The same definitions expose the initial `cascade.geo.*` library in Studio and
|
|
286
|
+
headless hosts: `Rectangle`, `Circle`, `Transform`, `Merge`, `CopyToPoints`,
|
|
287
|
+
and `SvgExport`. Their definitions, ports, and executors are runtime-owned;
|
|
288
|
+
Studio adapts them through its compatibility controller instead of maintaining
|
|
289
|
+
a second set of node algorithms.
|
|
290
|
+
|
|
291
|
+
## Current capability boundaries
|
|
292
|
+
|
|
293
|
+
| Surface | Current status |
|
|
294
|
+
| --- | --- |
|
|
295
|
+
| Studio authoring | Supports dynamic and definition-v1 nodes in one document through the compatibility controller. |
|
|
296
|
+
| Headless CLI | Executes all-definition-v1 or all-dynamic documents; mixed documents are rejected. Both styles can render frame sequences. |
|
|
297
|
+
| Embedded runtime | `cascade/runtime` is the neutral definition-v1 API for Node and browser hosts. It does not load Studio or interpret dynamic nodes. |
|
|
298
|
+
| 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). |
|
|
299
|
+
| Standalone HTML export | The existing Studio exporter uses a separate minimal runtime and supports only a subset of graph behavior. Treat it as an experimental convenience, not as a universal deployment artifact. |
|
|
300
|
+
| External services | Project-owned and optional. Cascade itself requires no paid provider or model subscription. |
|
|
270
301
|
|
|
271
302
|
## Repository map
|
|
272
303
|
|