Inference-depth anchoring playground: vertical + radial modes
The graph's follows/supports edges encode derivation (premise -> conclusion); the layout can now express that rank spatially, as a session-only playground toggle (nothing promoted yet): - inferenceDepths: longest chain from a base node, CYCLE-SAFE by SCC condensation (Tarjan, iterative) — the DAG property is typical, not guaranteed; cycle members share their component's depth (mutual support = equal footing). O(V+E), pure, deterministic. - DepthAnchor force: per-node target scalar — vertical mode rows (baseline at the anchor centroid, arrows up), radial mode rings (foundations center, outer boundary = edge of knowledge). The rank is computed, not simulated: pairwise up-forces can't give baselines. - Mode projections: gravity x-only in vertical / dropped in radial; cluster pull x-only in vertical / tangential-only in radial; the anchor re-blend preserves user arrangement in the FREE dimension only (x / angle) — meaning owns the constrained axis, memory owns the free one. - setPhysicsTuning reheats (alpha 1): toggling a mode re-forms the graph live and commits the new rest state; drag release is springy along the constrained axis (node returns toward its level/ring). - Sweep on the real graph: strength 0.8 = 215/216 arrows correct with organic sag; 1.5 = crisp rows. 174 base nodes, max chain depth 7, zero cycles in current data. replay-layout --depth=<mode> bakes a mode into the ledger for rest-state experiments.
This commit is contained in:
@@ -665,6 +665,41 @@ export function GraphView() {
|
||||
<span className="text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
|
||||
Physics
|
||||
</span>
|
||||
<label className="flex items-center justify-between gap-2 text-xs">
|
||||
Depth anchor
|
||||
<select
|
||||
className="rounded border bg-background px-1 py-0.5 text-xs"
|
||||
value={physicsTuning.depthMode}
|
||||
onChange={(e) =>
|
||||
setPhysicsTuning((t) => ({
|
||||
...t,
|
||||
depthMode: e.target.value as PhysicsTuning["depthMode"],
|
||||
}))
|
||||
}
|
||||
>
|
||||
<option value="off">Off</option>
|
||||
<option value="vertical">Vertical (up)</option>
|
||||
<option value="radial">Radial (outward)</option>
|
||||
</select>
|
||||
</label>
|
||||
<NumberField
|
||||
label="Depth strength"
|
||||
value={physicsTuning.depthStrength}
|
||||
step={0.05}
|
||||
onChange={(v) => setPhysicsTuning((t) => ({ ...t, depthStrength: v }))}
|
||||
/>
|
||||
<NumberField
|
||||
label="Depth spacing"
|
||||
value={physicsTuning.depthSpacing}
|
||||
step={10}
|
||||
onChange={(v) => setPhysicsTuning((t) => ({ ...t, depthSpacing: v }))}
|
||||
/>
|
||||
<NumberField
|
||||
label="Base ring radius"
|
||||
value={physicsTuning.depthBaseRadius}
|
||||
step={20}
|
||||
onChange={(v) => setPhysicsTuning((t) => ({ ...t, depthBaseRadius: v }))}
|
||||
/>
|
||||
<NumberField
|
||||
label="Node repulsion"
|
||||
value={physicsTuning.chargeStrength}
|
||||
|
||||
Reference in New Issue
Block a user