Files
learnharness/docs/vision-edge-glyph.md
T
amosblomqvist 65dfda2342 Withdraw the double-shaft edge glyph — both variants rejected live
The converged variant read as two arrows feeding one point; the two-
complete-arrows variant as two arrows next to each other, not coherent.
Owner withdrew the double-shaft idea entirely (2026-09-15); dashed was
already rejected 2026-09-14. Both relation types draw the same plain
single arrow again.

Kept: CanvasEdge.type plumbing from the snapshot (the next
differentiator will need it) and the ArrowGeom named type. Removed:
followsEdgeGeometry, the gap constants, the zoom-drift edge-path
rebuild (edges are back to a single loop in buildGeometry), the ⟹
legend entry, and the glyph tests. Vision doc records the withdrawal
and keeps the still-valid constraints.

Gates: tsc, 429/429 tests, lint, build. Live: canvas coverage 0.477,
no console errors, no legend remnants.
2026-09-15 08:38:13 +03:00

3.4 KiB

Vision — The edge glyph: follows vs supports

Ideation settled 2026-09-14. WITHDRAWN 2026-09-15: both shipped variants of the double-shaft glyph (tails converging on a shared head; two complete arrows offset ±half-gap) were rejected by the owner live — the first "two arrows feeding one point", the second "two arrows next to each other, not coherent". Dashed was already rejected 2026-09-14 (dash patterns crawl under the constant screen-space stroke width). The relation still needs a differentiator — approach open. The constraints below that are NOT glyph-specific still stand. Companion: vision.md § "Edges" (the relation types) and § "Rendering".

One line (withdrawn): the two relation types become visually distinct — follows renders as a double-shaft arrow (two parallel tails side by side, the implication glyph ⟹), supports stays a single line. Arrows keep their existing direction: prerequisite → dependent.


Why double-shaft (DECIDED 2026-09-14)

  • Semantically exact. follows means prerequisite ⇒ successor — derivability. The implication glyph is the relation; nothing encodes "derivable from" more literally.
  • Weight where the structure is. The DAG backbone (follows) gets the heavy glyph; the majority relation (supports is over half of all edges) stays light. The structural skeleton reads first.
  • Shape survives everything color can't. Cluster regions already own the color channel; a shape code collides with nothing and survives colorblindness.
  • Scale-stable. Pure geometry degrades nowhere — see the rejected alternative below.

Why not dashed (rejected 2026-09-14)

Dash patterns break under our constant screen-space stroke width: the dash array is re-projected across zoom levels, so the pattern pops and crawls instead of scaling cleanly (the same class of artifact as the non-integer blur radii). And with supports the majority relation, dashes would dominate the canvas rather than mark the exception. Dashed = wrong twice.

Geometry

The renderer is the custom 2D canvas; edges draw in the edge layer with shafts + arrowheads from arrowGeometry (sigma-style head, prerequisite → dependent). For follows:

  • Both shafts offset along the edge normal by a fixed screen-space gap.
  • REVISED 2026-09-15 (owner rejected the first cut): the converged variant — two tails merging into one shared arrowhead — read as two arrows feeding a single point, not as parallel strokes. The glyph is two complete regular arrows (own shaft + own head each) translated ±half-gap along the normal: parallel shafts AND parallel heads, nothing converges.
  • The gap is proportional to the constant stroke width — a constant visual ratio at every zoom level.
  • No LOD collapse (withdrawn 2026-09-14). The earlier idea of collapsing to a single shaft below a stroke-width threshold assumed width shrinks with zoom — it doesn't; stroke width is constant on screen, so the double shaft renders identically at every zoom level. Simpler than proposed: nothing to gate.

Legend and scope

  • Add a legend entry to the existing graph legend: ⟹ follows · → supports.
  • Main graph view only. The plan-block renderer (dagre) is untouched — the plan DAG is single-relation, so there is nothing to distinguish there.

Lane

lh-graph's renderer files (graph-canvas.ts, graph-view.tsx). Not assigned, not scheduled.