depgraph

Rules reference

Every live interaction that moves positions is expressed as a moment on the dispatcher. Each moment names the rule whose tick(moment, ctx) will be called every frame while the moment is live. A rule returns a posDeltas map (id -> {dx, dy}) that the dispatcher composes additively onto posMap, so two moments targeting the same node produce the vector sum of their contributions.

This document is the per-rule reference. The substrate itself (moments, HLC coordinates, emit / retract / commit, tick) lives in src/core/dispatcher.js and is documented in-module.

Rule contract

rule = {
  name: string,
  tick(moment, ctx) -> { posDeltas?: Map<id, {dx,dy}> } | null
}

Rules must NOT mutate posMap directly — the dispatcher enforces composition by applying posDeltas itself, skipping locked members. The one exception is relax, which snapshots, runs an imperative descentStep, and rolls back before returning the diff.


gather — src/rules/gather.js

Pulls members toward a target point with a per-frame lerp. Used for the Space-bar gather gesture (centroid, cluster, and stranger flavors).

Payload

Context

Behavior

Helpers


drag — src/rules/drag.js

Snaps members to anchor + offset. Unified over node drag, group drag, and cluster-label drag — every flavor is “members rigidly translate with a moving anchor point.”

Payload

Context

Behavior

Helpers


relax — src/rules/relax.js

One gradient-descent step per tick, expressed as position deltas. Collapses the X-key reset and the cluster-expand descent-burst into a single rule.

Payload

Context

Side-effect discipline descentStep mutates posMap imperatively. The rule snapshots, runs the step, diffs to produce posDeltas, and rolls posMap back to pre-step state. The dispatcher then re-applies the deltas (with its own locked-check) alongside any other live moments’ contributions, preserving additive composition.


arrangement-pull — src/rules/arrangement-pull.js

Walks the arrangement stack as time elapses, snapping posMap to each snapshot via position deltas. Re-expresses the legacy updateTravel() per-frame cursor walk.

Payload

Context

Behavior

Bookkeeping lives outside Start / stop bookkeeping (the z-pending and z-travel labels that arrangements.startTravel / stopTravel manage) is a once-per-gesture concern, not a per-frame one. The dispatcher doesn’t need to own it; the caller keeps calling startTravel / stopTravel around the moment.


cluster-rules — src/rules/cluster-rules.js

Not a dispatcher rule. This module is a set of history-row builders that mutate the stretch scalar on a cluster’s memberOf edges. The gradient descent loop then animates the layout toward the new equilibrium — no render-layer swap, no inward tween, the physics IS the animation.

Stretch semantics (see src/layout/gradient.js): target = BASE * exp(stretch).

Canonical values

Exports


click-events — src/rules/click-events.js

Not a dispatcher rule. This module records clicks as graph edges so downstream consumers (gather, trace, reset) can query “what was last clicked” without a separate JS object.

A sentinel node mouse-clicked lives in the graph. Each click appends an event:click edge from the sentinel to the click target. The edge layer has zero weight, so clicks accumulate in history without warping the graph.

Exports


Stubs (not yet implemented)

These modules exist as placeholders for the phase-11 user-authored-rules work. They export names so imports don’t break, but the bodies are empty.