Files
Understand-Anything/understand-anything-plugin
T
d ๐Ÿ”น 988533a550 fix(dashboard): preserve any-layer-wins membership for filterNodes
Reviewer @Lum1104 (PR #112) caught a silent semantic regression: the new
`filterNodes` reads layer membership through `nodeIdToLayerId.get(node.id)`,
which is first-wins. The pre-#112 path was any-layer-wins โ€”
`layers.some(layer => filters.layerIds.has(layer.id) && layer.nodeIds.includes(node.id))`.
For a node X listed in both L1 and L2 with only L2 selected, the old code
kept X; the new code dropped it. The schema permits multi-layer membership,
so this was a behavior change, not a bug fix.

Fix: keep two distinct indexes in the store. Both are rebuilt once on
`setGraph`, so the O(1)-per-node performance win from #112 is preserved.

  - `nodeIdToLayerId: Map<string, string>` โ€” first-matching-layer wins.
    Drives navigation (drillIntoLayer / tour step โ†’ layer / sidebar
    history) where one canonical layer is the right answer. Unchanged.

  - `nodeIdToLayerIds: Map<string, Set<string>>` โ€” every layer the node
    belongs to. Drives `filterNodes` membership checks. Restores
    any-layer-wins exactly.

`filterNodes` now iterates the (small) layer-id set per node looking for
intersection with `filters.layerIds`. ExportMenu reads
`nodeIdToLayerIds` from the store.

Verified locally:

  - Added `filters.test.ts` regression: node in (L1, L2) with only L2
    selected must pass. Failed against the first-wins implementation;
    passes now.
  - `pnpm --filter @understand-anything/dashboard test` โ€” 42 / 42 pass
    (was 41; +1 multi-layer regression test; perf-guard at 100 layers ร—
    100 nodes still <50 ms).
  - `pnpm --filter @understand-anything/dashboard exec tsc --noEmit` โ€” clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
988533a550 ยท 2026-05-04 17:16:42 +08:00
History
..
2026-05-03 18:16:02 +08:00
2026-05-03 18:16:02 +08:00