feat(viz): cluster the Knowledge graph — each pitfall is a box holding its incident history#26
Merged
Merged
Conversation
…g its incident history (ADR-45) The Knowledge tab rendered pitfalls in one row and incidents in another with a dense mesh of crossing `from`/`about` edges — a hairball that hid the structure (which lesson owns which history) exactly where the differentiator data lives. Now each Pitfall/Suppression is a Cytoscape compound box containing its incidents: - VizNode.parent (model) — collectKnowledge nests each incident inside the first pitfall that cites it; containment replaces the redundant `from`/`about` edge. A second citer of a shared incident keeps a cross-cluster edge (one compound parent only). - :parent style — a tinted, type-coloured box with the lesson title pinned top; children keep their own colour + outcome/sentinel borders. - knowledgeGrid — lays the lesson-boxes in a deterministic grid and packs each box's incidents in a mini-grid (preset positions). cose/force layouts band the edge-less clusters into an overlapping strip, so a hand-rolled grid is used rather than adding the fcose extension (keeps the SRI/dep surface minimal). - Incident dots drop their (colliding) file-path label — shown on select; the box title + outcome ring carry the meaning. Tests: collect.test asserts incidents nest via `parent` + a cross-cluster `from` edge is kept for a shared incident; ui.test asserts the `:parent` style + knowledgeGrid. Verified against the populated playright/global knowledge base (26 pitfalls / 96 incidents / 6 suppressions) — the hairball is now a readable grid of lessons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ross-cluster edge + size grid cells to fit (PR #26 review) Address the Plex self-review of PR #26: - BUG: the `node[type="Incident"]{text-opacity:0}` label-hide was GLOBAL, so it also blanked incident labels in the code-graph symbol↔incident expand and in Lineage — views the PR doesn't touch. The Incident node always carries graph:'knowledge' (it's the same incidentVizNode reused across views), so it can't be node-scoped; gate the rule on the CURRENT graph instead — styleFor(graph) adds it only for knowledge. - NIT: an incident both cited by a pitfall (incidentIds) and carrying pitfallId for that same non-container pitfall got both a `from` (pf→inc) and an `about` (inc→pf) edge — duplicate arrows for one link. Track cross-cluster `from` pairs and skip the redundant `about`. - FLAG: the fixed 360x250 grid cell could be overflowed by a high-incident pitfall, spilling into the row below and overlapping a neighbour (positions are fixed). Size the uniform cell from the LARGEST box (+title/padding) so every box's mini-grid fits. Tests: collect.test gains a from/about de-dup case; the existing label assertion still holds (the rule string is emitted, now inside the knowledge branch). Verified against the populated base — boxes read cleanly, the 16- and 24-incident boxes fit without overlap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The Knowledge tab rendered pitfalls in one row and incidents in another, joined by a dense mesh of crossing
from/aboutedges — a hairball that hid the one thing that matters most (which lesson owns which history), exactly where Plex's differentiator data lives. This clusters it: each Pitfall/Suppression is now a box holding its incident history.VizNode.parent(model) —collectKnowledgenests each incident inside the first pitfall that cites it; the containment replaces the redundantfrom/aboutedge. A second pitfall citing a shared incident keeps a cross-cluster edge (a Cytoscape compound node has one parent only), so shared provenance stays visible.:parentstyle — a tinted, type-coloured box with the lesson title pinned top; children keep their own colour + the existing outcome (green/red border) and regression-sentinel (orange ring) encoding.knowledgeGrid— lays the lesson-boxes in a deterministic grid and packs each box's incidents in a mini-grid (presetpositions). cose/force layouts band the (edge-less) clusters into one overlapping strip, so a hand-rolled grid is used instead of adding thefcoseextension — keeps the CDN/SRI/dependency surface minimal (ADR-35 posture).Result: the hairball becomes a readable grid of lessons — suppressions (red boxes) clearly distinct from pitfalls (teal), each box's incident count and outcomes visible at a glance.
How to test
pnpm test:unit(549) —collect.testasserts incidents nest viaparentand that a cross-clusterfromedge is kept for a shared incident;ui.testasserts the:parentstyle +knowledgeGrid.pnpm typecheck+pnpm buildgreen.plex serve→ Knowledge tab (try "All repos (global)" and a repo scope). Verified against the populated playright/global base (26 pitfalls / 96 incidents / 6 suppressions).Notes
Scope is the Knowledge graph only — the code-graph "800-file cold dump" landing state is a separate follow-up (the other hairball from the viz-validation pass). Lineage/Review-history is unchanged (already legible).
🤖 Generated with Claude Code