|
| 1 | +--- |
| 2 | +id: AILOG-2026-06-14-001 |
| 3 | +title: Loom R3 — legibility at 100+ nodes (label density + hide isolated) |
| 4 | +status: accepted |
| 5 | +created: 2026-06-14 |
| 6 | +agent: claude-fable-5 |
| 7 | +confidence: high |
| 8 | +review_required: true |
| 9 | +risk_level: low |
| 10 | +eu_ai_act_risk: not_applicable |
| 11 | +nist_genai_risks: [] |
| 12 | +iso_42001_clause: [] |
| 13 | +lines_changed: 140 |
| 14 | +files_modified: [CHANGELOG.md, Cargo.lock, README.md, docs/adopters/CLI-REFERENCE.md, docs/i18n/es/README.md, docs/i18n/es/adopters/CLI-REFERENCE.md, docs/i18n/zh-CN/README.md, docs/i18n/zh-CN/adopters/CLI-REFERENCE.md, experimento/CHANGELOG.md, experimento/Cargo.toml, experimento/web/index.html, experimento/web/package.json, experimento/web/src/i18n.ts, experimento/web/src/main.ts] |
| 15 | +observability_scope: none |
| 16 | +tags: [loom, ui, density, labels, knowledge-graph] |
| 17 | +related: [AILOG-2026-06-13-002, AILOG-2026-06-12-002] |
| 18 | +--- |
| 19 | + |
| 20 | +# AILOG: Loom R3 — legibility at 100+ nodes |
| 21 | + |
| 22 | +## Summary |
| 23 | + |
| 24 | +Closes the last Loom UX follow-up (R3). After R2 the Sentinel graph reached ~195 nodes and the |
| 25 | +visualization got noisy. The operator picked the two pain points to address: **noisy labels** |
| 26 | +and **isolated nodes cluttering the canvas**. Frontend-only; ships as `loom-0.4.2`. |
| 27 | + |
| 28 | +## Actions Performed |
| 29 | + |
| 30 | +1. **Label density cap.** Added Sigma `labelDensity: 0.6` / `labelGridCellSize: 180` and raised |
| 31 | + `labelRenderedSizeThreshold` to 10. Sigma labels the highest-`size` node per screen-grid |
| 32 | + cell; since nodes are sized by centrality (`applySizing`, default betweenness), the surviving |
| 33 | + labels are the important ones. Zooming in reveals more. The hovered/selected node gets |
| 34 | + `forceLabel: true` so its full label always shows. |
| 35 | +2. **"Labels" toggle** (header checkbox, default on): `renderer.setSetting('renderLabels', …)` |
| 36 | + for a pure-structure view. |
| 37 | +3. **"Hide isolated" toggle** (header checkbox, default off): a precomputed `isolated` set |
| 38 | + (`graph.degree(id) === 0`, recomputed per rebuild) drives an early `nodeReducer` branch that |
| 39 | + returns `{ hidden: true }`, removing singleton/orphan nodes from the canvas and from label |
| 40 | + consideration. The toggle shows the hidden count. |
| 41 | +4. **i18n** for the two controls (`view.labels`, `view.hideIsolated`) in en/es/zh-CN; listeners |
| 42 | + wired once (consistent with the 0.4.1 delegation fix). |
| 43 | +5. **On-screen zoom / fit controls** (bottom-right): zoom-in / zoom-out (`camera.animatedZoom` |
| 44 | + /`animatedUnzoom` with an explicit step) and fit-to-view (`animatedReset`). Also lowered the |
| 45 | + wheel/pinch `zoomingRatio` (1.7 → 1.4) — operator feedback that trackpad pinch zoom felt |
| 46 | + over-accelerated on a multitouch (Magic Trackpad) device. i18n tooltips `zoom.in/out/reset`. |
| 47 | + |
| 48 | +## Decisions Made |
| 49 | + |
| 50 | +- **Tuned defaults over a manual density slider.** Centrality sizing already ranks nodes, so |
| 51 | + Sigma's per-cell label heuristic needed only coarser grid settings — no new ranking code. |
| 52 | +- **Hide isolated via the reducer, not by dropping nodes.** Keeps the data/graph intact (stats |
| 53 | + and the legend's isolated count stay accurate); only the render hides them. |
| 54 | +- **Did not touch the force layout or edges.** The operator did not flag a hairball; R3 stays |
| 55 | + scoped to labels + isolated nodes. |
| 56 | + |
| 57 | +## Impact |
| 58 | + |
| 59 | +- **Functionality:** additive view controls; default render is less cluttered at scale. No API, |
| 60 | + backend or core change (`straymark-core` stays 0.4.1). |
| 61 | +- **Security/perf:** unchanged; the isolated set is precomputed per rebuild, not per frame. |
| 62 | + |
| 63 | +## Verification |
| 64 | + |
| 65 | +- [x] `npm run build` — tsc + vite pass (Sigma settings, `forceLabel`/`hidden`/`setSetting` |
| 66 | + types valid). |
| 67 | +- [x] Served HTML exposes both toggles; `/api/stats` healthy (197 nodes on Sentinel); forged |
| 68 | + `Host` → 403. |
| 69 | +- [ ] Visual acceptance (operator): fewer/important labels by default, zoom reveals more, |
| 70 | + Labels-off hides them, Hide-isolated removes the loose nodes. |
| 71 | + |
| 72 | +## Follow-ups |
| 73 | + |
| 74 | +- Loom's Knowledge-Graph track (M0–M3) and all connectivity/UX follow-ups (R1–R3) are now done. |
| 75 | + The next frontier is the Architecture track (A1/A2, Spec 002) and graduation (N=2). |
| 76 | + |
| 77 | +--- |
| 78 | + |
| 79 | +<!-- Template: StrayMark | https://strangedays.tech --> |
0 commit comments