Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
af19e86
fix(graph): place relationship labels on their turned boxes
mvalancy Nov 11, 2026
898d6a4
feat(graph): let Organize reserve a gap per connection
mvalancy Nov 11, 2026
d24871b
feat(graph): hierarchical rows with room for relationship labels
mvalancy Nov 11, 2026
a1ed8c2
feat(graph): label clearance for automatic layouts
mvalancy Nov 11, 2026
68a9ae5
fix(graph): Organize, hierarchical and force layouts leave label room
mvalancy Nov 11, 2026
b299856
test(graph): organize-labels journey on desktop, iPad and iPhone
mvalancy Nov 11, 2026
dca5a62
fix(graph): labels show while card titles do; small graphs framed whole
mvalancy Nov 11, 2026
4946cdb
test(graph): organize-labels checks the resting camera, whole graph a…
mvalancy Nov 11, 2026
257aa27
fix(graph): small graphs framed down to the label cutoff, never on no…
mvalancy Nov 11, 2026
944717e
test(graph): count cards under a control apart from cards off screen
mvalancy Nov 11, 2026
9beb216
Check each label only against what can reach it
mvalancy Nov 11, 2026
ddc0350
Bound the label-room search to small graphs and a fixed budget
mvalancy Nov 11, 2026
dcfa739
Spread a component along the screen's long side when that frames closer
mvalancy Nov 11, 2026
e209be3
Tests: every relationship drawn, turned label outlines, hub reads on …
mvalancy Nov 11, 2026
254e80e
Merge remote-tracking branch 'origin/dev' into fix/label-clear-layout
mvalancy Nov 11, 2026
17c4f66
Phones keep the organized floor after Organize
mvalancy Nov 11, 2026
f966a14
Drop the long-side spread
mvalancy Nov 11, 2026
23ee7b3
Keep only checked spreads and check the finished layout as a whole
mvalancy Nov 11, 2026
91bef6d
Retry a missing label from fresh spots in small graphs
mvalancy Nov 11, 2026
33ce711
Merge dev (zoom-out levels #279, example resume #282) into label room
mvalancy Nov 11, 2026
a8ce902
Break card titles only at spaces
mvalancy Nov 11, 2026
63c8f28
Merge dev (relationship edit #281) into label room
mvalancy Nov 11, 2026
82ade7f
Move a settled free card only for its own labels
mvalancy Nov 11, 2026
84a22da
Keep dev's hierarchical rows above 60 cards
mvalancy Nov 11, 2026
018a73b
Open a graph of unplaced items as dev does
mvalancy Nov 11, 2026
a8804e4
Show paths and identifiers in full while title lines are left
mvalancy Nov 11, 2026
05ca677
Retry labels from fresh spots only when one on screen was missed
mvalancy Nov 11, 2026
071c783
Merge dev (installer network retry #287) into label room
mvalancy Nov 11, 2026
9b5c914
Keep dev's hierarchical layout at every size
mvalancy Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .agents/inbox/2026-11-10-layouts-must-leave-label-room.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Automatic layouts must leave room for every relationship label

Observed 2026-11-10 after the owner reported that "Organize around connections"
and the force layout put cards so close that relationship labels disappear. The
renderer only draws a label where the whole label clears every card, arrowhead,
other wire and earlier label (`edgeRouteLabel`); otherwise it hides it. The
layouts kept cards 64px apart (organize, hierarchical rows) or guessed label
widths (force), so most labels had nowhere to go. Earlier lessons on clearance
(`2026-10-28-clean-layout-needs-clearance-and-topology.md`) and fitting
(`2026-11-07-fit-must-measure-presented-geometry.md`) were read first; this
concerns the room between connected cards.

## Evidence

- `tests/e2e/journeys/organize-labels.spec.ts` against the unchanged `dev`
source (3a629e2), desktop: Welcome organized 0 of 3 labels shown; Plan a
launch organized 7 of 8 in-view labels hidden; hierarchical hid 2-33 labels per
graph; a settled force layout from unplaced items hid 1-47 per graph (Dense
cluster of 30: all 47). iPad and iPhone failed the same way. No label was ever
drawn on a card or another label: the renderer hides instead, so the symptom
is missing labels, not overlap.
- `labelClearance.test.ts` places every label as the renderer does over whole
layouts of the same shapes on three screen sizes: the old organizer hid 2-13
labels per shape at the zoom it frames them, the old hierarchical rows 2-47.
- Labels keep their screen size below 100% zoom, so in graph units they grow by
1/zoom: "Organize" frames at no less than 65%, where a label needs half as
much room again as at 100%.

## Cause and corrective rule

- Every automatic layout reserves, for each drawn edge, a visible
(border-to-border) length of `labelGap(label, zoom)`: the measured label at the
zoom the camera will frame the result, its clearance at both ends and the
arrowhead. Lay out, compute the framing (`computeGraphFit` with the controls as
obstacles, and the floor), and lay out again when that zoom needs more room.
- Reserved gaps are not enough where wires cross labels: check the result by
placing labels exactly as the renderer does (`placeGraphLabels`) and spread
the group by the smallest factor that frees them (`spreadForLabels`).
- Check the layout the renderer will get, under any ids: real ids are random
and break ties in the organizer and the label order. Keep only spreads that
were checked, check the finished layout as a whole (`checkedWhole`), and
test several id orders (`label room whatever the item ids`). The renderer
starts each label from its spot in the previous frame; in a small graph,
when a label on screen found no spot (`labelsMissed`), it retries from fresh
spots, the placement the layouts leave room for.
- Never move a saved or organized (pinned) card to make room; after the force
layout settles, move only the cards it placed itself (`clearFreeCards`), only
for labels with such a card at one end, and keep a move only when it shows
more of them. A label between two saved cards once made a new card in a
saved graph fly 4 and then 16 times as far away; now nothing moves for it.
- Test readability with the renderer's own geometry: the browser audit reads
every label from the DOM (turned boxes, `elementFromPoint`) and an edge whose
cards are on screen and clear of the controls must show its label.

## Limits

The search runs in the click handler, so its work is bounded: at most
`WHOLE_FIT_MAX_CARDS` (60) cards, `LAYOUT_CHECKS` label checks and five
layouts per click (about 100 ms on a desktop; a unit test guards it). Larger
graphs keep the plain layouts and the 0.65 Organize floor (an early version
searched up to 200 cards and froze the page for seconds). A phone keeps the
0.65 Organize floor: two compact cards and a label side by side do not fit
390 px at a zoom where titles still fit whole (below about 0.45 a long word is
cut short), so a whole graph there needs compact label chips. The
hierarchical layout and the first open of a graph of unplaced items stay as
they were: label room in hierarchical rows that still wrap like dev's (a hub
with many dependents) is #283. A graph's saved
arrangement is never moved, so labels hidden there stay hidden until the person
organizes. Labels under a control or the MiniMap are a camera matter, recorded
by the audit but not counted.
2 changes: 1 addition & 1 deletion .agents/inbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test name or file path. Lessons so far cover:

| Topic | Example lessons |
| --- | --- |
| Graph rendering, LOD and layout | `2026-10-29-high-degree-detail-needs-local-lod.md`, `2026-11-07-fit-must-measure-presented-geometry.md` |
| Graph rendering, LOD and layout | `2026-10-29-high-degree-detail-needs-local-lod.md`, `2026-11-07-fit-must-measure-presented-geometry.md`, `2026-11-10-layouts-must-leave-label-room.md` |
| Interaction and focus | `2026-10-28-drag-mode-must-survive-modifier-release.md`, `2026-10-27-delayed-autofocus-must-preserve-chosen-focus.md` |
| Auth and security | `2026-10-23-magic-link-consumption.md`, `2026-10-27-captcha-proof-must-be-server-issued.md` |
| Releases, CI and dependencies | `2026-10-23-release-gates-must-fail-closed.md`, `2026-10-28-advisories-follow-installed-consumers.md` |
Expand Down
1 change: 1 addition & 0 deletions .agents/issues/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
| --- | --- |
| A dense item shows a fan of essential wires while every neighbor is off screen, despite settled/no-overlap metrics | [Detailed LOD needs a readable local cut](../inbox/2026-10-29-high-degree-detail-needs-local-lod.md); EPIC2215 owned301 failure and local-neighborhood acceptance |
| Overview has no intersections but wires hug cards/each other, or hubs are flattened into rows | [Measure clearance and organize by topology](../inbox/2026-10-28-clean-layout-needs-clearance-and-topology.md); topology/overview organization tests, real control/save journey and strict schematic clearance |
| Relationship labels disappear after "Organize around connections", in hierarchical mode or once the force layout settles | [Layouts must leave room for every label](../inbox/2026-11-10-layouts-must-leave-label-room.md); `labelClearance.test.ts`, `organize-labels` browser sequence |
| Zoom to fit alternates compact/full cards on phones; focus returned after quick edit or expand lands on `<body>` | [Fit the presented geometry; focus follows detail](../inbox/2026-11-07-fit-must-measure-presented-geometry.md); `graphFit.test.ts`, `fit-focus.spec.ts`, `agent-approval.spec.ts` |
| Overview zoom exceeds five seconds while original item groups are hidden | [Hidden items must not delay overview](../inbox/2026-10-29-hidden-items-must-not-delay-overview.md); issue #235, retained actual-dev 2k failure |
| Overview wires cannot be hovered, do not light endpoints, or lose focus when their route disappears | [Interaction geometry and original-edge inspection](../inbox/2026-10-28-overview-wires-need-interaction-geometry.md); `OverviewBusLayer`, semantic LOD and 2k bus inspection journeys |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ jobs:
semantic-lod ci-semantic-lod xvfb
layout-recovery ci-layout-recovery xvfb
example-resume ci-example-resume
organize-labels ci-organize-labels
relationship-edit ci-relationship-edit
services:
neo4j:
Expand Down
Loading
Loading