Skip to content

0.10.0

Latest

Choose a tag to compare

@marcuswendt marcuswendt released this 12 Oct 06:21
· 73 commits to main since this release

Added

  • The timeline is saved with the graph. timeline: { fps, start, end, loop } in the document: Studio's Timeline opens on it and writes it back,
    the runtime uses its fps, and cascade run --frames timeline renders its
    range.

  • run --frames … --mp4 <file> [--crf N] encodes the rendered sequence
    with ffmpeg as H.264 yuv420p at the run's fps, and reports it as video in
    the --json manifest.

  • Stage cache keys Cascade owns. Every Python stage call, Studio or
    headless, is keyed on the stage code (a hash of exec.stages.sources), the
    arguments with input files replaced by their content hash, and the Cascade
    version, and its cache state (hit, miss, off) and key are reported on
    every call: in the server log, in run --json under stages, and in the run
    trace. exec.stages.cache turns on a core result cache that verifies the
    files a stored result names before serving it.

  • Run traces. Every cascade run writes .cascade/runs/<time>-<graph>.json
    with each node's time and its stage calls. run --json works without
    --frames.

  • Seeds. context.seed (from the document's seed and the node id) and
    context.random() in both hosts; cascade run --seed N.

  • cascade parity <graph> [--node] [--tolerance] [--json] cooks headless
    twice and through Studio's executor with caches off and reports every node
    output side by side.

  • Locks and replay. cascade lock <graph> <node> --name <name> records one
    render in locks/<id>.json: the graph as cooked, every prop and seed, input
    file hashes, the project's source code (stored by hash in
    .cascade/objects/), versions and git state, and a fingerprint of every
    output. cascade replay <id> rebuilds that code in a throwaway copy of the
    project and compares fingerprints, without a worktree; --live uses the
    current code instead. cascade lock verify replays every lock and
    cascade locks lists them. All take --json.

  • cascade serve. start | stop | restart | status | logs | install | uninstall [project] runs Studio as a supervised background service: one
    lock, record and log per project under ~/.cascade/serve/, restart with
    backoff after a crash, and a stop that takes the Python worker with it.
    status --json reports port, actual host, pids, uptime, version and worker
    state. install writes and loads a macOS launchd job.

  • Host fallback. When --host does not resolve (a MagicDNS name while
    Tailscale is down) or is not on this machine (EADDRNOTAVAIL), Studio binds
    127.0.0.1 (or --fallback-host, repeatable) instead of crashing, and moves
    back to the preferred host when it returns.

  • 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.

  • --json on every command: one { ok, data, warnings } envelope on stdout.

  • 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.

  • The editing API (GraphEditor, readGraph, the operation types) is exported from @field/cascade/runtime.

Changed

  • cascade run --frames --json prints its manifest inside the envelope, as data, rather than at the top level.

Fixed

  • Headless frame renders no longer start Python per stage per frame.
    cascade run uses the project's warm worker for the whole run, and frames
    after the first re-cook only what the frame changed (reuse: "strict";
    --fresh cooks everything). cloud-plots' morph, frames 1–60: 588 s to 5 s,
    byte-identical.

  • An edited stage no longer runs its old code in a live Studio. The warm
    Python worker restarts before the next request when its stage sources
    change, with Python's bytecode cache keyed by the code hash so a quick
    same-length edit is not served from an old .pyc.

  • A failed build keeps the previous dist/. npm run build and
    build:cli build into .dist-staging/ and swap it in only when every step
    passed; the log names the step that failed.