Skip to content

Node Snapshot Diff Replay

coo1white edited this page Jun 8, 2026 · 1 revision

Node Snapshot / Diff / Replay (v0.1.35)

Per-NODE granularity over the v0.1.23 eval/replay harness: snapshot one StateNode, diff two snapshots structurally, and deterministically replay one node in isolation. Shipped in v0.1.35. Repo doc: docs/node-snapshot-diff-replay.7.md.

Before v0.1.35 the eval harness worked only at RUN/SUITE granularity. v0.1.35 adds per-node snapshot/diff/replay, reusing the harness's normalize/stable-stringify discipline and the v0.1.25 fingerprint/freshness pattern — without forking StateNode, the harness, or the run-state schema (all additive).

Design Mantra

Snapshot is derived, fingerprinted, not the source.
Fail closed on drift: valid | stale | absent.
Replay injects now; the payload has no wall-clock.
Two replays are byte-identical.

The Borrowed Idea: A Fingerprinted Derived Projection

A NodeSnapshot is a normalized projection of one node (timestamps/paths stripped via the eval normalizer, so it is byte-stable across captures of the same logical state) plus a sourceFingerprint — sha256 over the RAW node (id:status:updatedAt + artifact/evidence ids+paths), so any transition flips it. The source StateNode JSON stays the truth.

Principles

  1. Snapshotnode snapshot <run> <node>; content-addressed id (snap-<node>-<fingerprint>), persisted under <run>/nodes/snapshots/<node>/.
  2. Fail closed on drift (load-bearing) — every load recomputes the fingerprint: valid (matches), stale (source changed), absent (node or a referenced artifact path gone). stale/absent REFUSE diff/replay with a structured error — never a silent stale replay.
  3. Diffnode diff <baseline> <candidate>: per-section (status/inputs/outputs/artifacts/evidence/errors/links/metadata) added|removed|changed|same, ordered by the same stableStringify the eval comparison uses; byte-identical across runs.
  4. Replaynode replay <snapshot>: reconstructs the node with now INJECTED (no ambient new Date()); the deterministic payload (body + outputFingerprint) carries zero wall-clock, so two replays are byte-identical (only replayedAt/replayId differ). Replaying a stale/absent snapshot fails closed.
  5. Verifynode verify <replay>: compares a replay to a fresh snapshot of the source, with findings in the eval harness's severity/category/reason shape.
  6. Reuse, don't fork — exported the previously-private normalizeValue/stableStringify/lines (eval harness) and fingerprintStrings (state-explosion); additive, no behavior change.

Why It Matters

Run/suite replay tells you a whole run reproduced; per-node replay lets you pin-point WHICH node drifted and reproduce just it, deterministically — the unit a debugger actually wants. Verified live: snapshot → replay → diff a real node via the CLI, byte-identical, no wall-clock leak.

See Also

  • Architecture Principles
  • CLI MCP Parity
  • Eval/Replay Harness — plugins/cool-workflow/docs/multi-agent-eval-replay-harness.7.md
  • State Explosion Management — plugins/cool-workflow/docs/state-explosion-management.7.md
  • Repo doc: plugins/cool-workflow/docs/node-snapshot-diff-replay.7.md

Clone this wiki locally