Files
socraticode/src/assets
Giancarlo Erra e4da76979e feat(visualize): symbol view as focus graph; UX polish & stats consistency
Symbol view (full rebuild)
──────────────────────────
Replaces the unusable "show all symbols at once" mode with a focus
graph (SourceTrail / IntelliJ pattern):

- Landing state shows the alphabetical list of all symbols in the
  sidebar; canvas shows a "pick a symbol" overlay constrained to the
  canvas area (right: 340px) so the list stays visible.
- Three entry paths to seed: list click, search bar, or symbol click
  from a file's sidebar in Files view.
- Once seeded, canvas shows the symbol + its 2-hop callers/callees
  neighbourhood (auto-falls back to depth 1 if > 60 nodes).
- Clicking any neighbour re-centres on it. Seed has a distinctive
  orange ring + always-visible label so the anchor is obvious.
- "← Back to symbol list" link in the sidebar restores the empty
  state — explicit way out instead of relying on accidental
  empty-canvas clicks.
- Light file-grouping: each symbol's border colour is a stable hash
  of its file path; symbols from the same file share a colour.

Layout dropdown clean-up
────────────────────────
Removed Force-directed (cose). Force-directed is the wrong algorithm
for code dependency graphs — hub clusters collapse, orphans fly off,
labels overlap, no tuning fixes the underlying shape mismatch. Tried
fcose as a substitute; same fundamental problem on dense code graphs.
Default is now Dagre TB; remaining options are Concentric, Breadth-
first, Grid, Circle — all deterministic.

UX polish
─────────
- autoungrabify: true — disables single-click drag, fixes "node jumps
  on click" (trackpad clicks always have some motion which Cytoscape's
  default interprets as a node grab).
- Tap-to-highlight neighbourhood — clicking any node highlights its
  direct neighbours and fades the rest. Less aggressive than the
  transitive blast-radius / call-flow buttons in the sidebar.
- Zoom-bound label visibility — labels hidden below zoom 0.55 so 100+
  node graphs aren't a soup of overlapping text. Selected / highlighted
  nodes always show their label.
- Layout-position persistence — switching Files ↔ Symbols and back
  preserves Files-view positions instead of re-running the layout.

TDZ regression test
───────────────────
New tests/unit/viewer-app.test.ts runs the bundled viewer-app.js in a
sandboxed node:vm context with mocked DOM + Cytoscape, triggering
every function-typed style closure on a fake element. Catches TDZ
("Cannot access X before initialization") and other reference errors
at unit-test time. Would have caught both the prior `cy` and
`LABEL_ZOOM_THRESHOLD` ordering bugs before they reached the browser.

Stats-line consistency
──────────────────────
graph-visualize-html.ts — top bar now displays embedded counts
(sym.symbols.length / sym.symbolEdges.length) instead of meta counts.
Previously the top bar said "630 symbols" while the sidebar's "All
symbols" said "722" because meta excludes synthetic <module>
placeholders. Capped mode keeps meta counts with a "(capped)"
qualifier since the embedded set is empty there.

Quality gates
─────────────
- Biome lint: clean
- TypeScript (tsc): clean
- Unit tests: 687/687 (incl. the new viewer-app.js evaluation test)
2026-04-27 17:46:51 +01:00
..