Files
Understand-Anything/understand-anything-plugin
d 🔹andClaude Opus 4.7 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>
2026-05-04 17:16:42 +08:00
..
2026-05-03 18:16:02 +08:00
2026-05-03 18:16:02 +08:00