Registration options for Graph.derived.

Named and generic since causl/causl-wasm-ts#267: the bag used to be an inline anonymous type carrying only the engine-internal tag, and key is both its first consumer-facing member and its first member that is generic in T. The shape is PURELY ADDITIVE — tag is carried unchanged, so no existing derived(...) / liveDerived(...) / commitMetadataDerived(...) call site is edited.

interface DerivedOptions<T> {
    key?: (value: T) => unknown;
    tag?: "live" | "commit-metadata";
}

Type Parameters

  • T

    Value type produced by the derivation, so key can be typed against the value it projects from.

Properties

Properties

key?: (value: T) => unknown

Marker-expressible CUTOFF projection: the part of the derivation's value that decides whether the node counts as changed.

The engine's derived cutoff normally compares the structural content-hash of the WHOLE value (SPEC §5.1 Amendment 7). Supplying key substitutes key(value) as the subject of that relation: the derivation counts as changed iff the PROJECTION's marker moved. On a grid-sized value that removes the O(|value|) traversal outright rather than optimising it.

Four things it does NOT do:

  • it does not change what read() serves — the value is retained verbatim, exactly as for an un-keyed derivation;
  • it does not suppress the keyed node's own recompute, which still runs whenever its dependencies move. key governs PROPAGATION, not evaluation;
  • it is not consulted when the derivation's value is a SCALAR. A scalar is already O(1) to compare and both engines cut it off by its own wire scalar record, so a projection there buys a cutoff strictly less sensitive than the one already in force;
  • it is not an escape hatch from the value domain. A projection the marker cannot REPRESENT (function / symbol / bigint) is accepted at construction — a projection is a function OF THE VALUE, so a construction-time probe could only ever sample the registration-time value — and REFUSES elision: the node is reported changed on every commit. Slower, never stale.

Invoked once per publish, inside the commit. It is consumer code and may throw; a throw aborts the commit and rolls it back atomically (§5.2), identically to a throwing compute.

tag?: "live" | "commit-metadata"

Engine-internal registration tag. tag: 'live' is used by liveDerived (devtools) so graph.explain reports via: 'live' for hot-swappable nodes; tag: 'commit-metadata' is set by Graph.commitMetadataDerived and schedules the node in Phase F.5. Adopters do not pass this directly.