feat(lineage): show impact badges on direct upstream/downstream in Lineage tab#1352
Conversation
Brings the canvas Impact Analysis signal into the Model Detail panel's
Lineage tab so users don't have to cross-reference rows against the graph.
When the focused node is in the impact set, direct neighbors that also
participate are decorated with an amber left rail, an 8% amber tint, and
a trailing arrow icon. Tooltip differs by direction: upstream rows show
"Impacts this model"; downstream rows show "Impacted by this model". The
section header gains a count chip ("N impacting" / "N impacted") and stays
silent at zero, matching design DRC-3344 (variant D).
NodeViewOss reads impactedNodeIds from LineageViewContext and forwards it
to LineageTabContent as an optional prop, so existing tests and Storybook
mounts that don't wrap the provider keep rendering as today.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
Two changes on top of the initial Lineage-tab impact marks: - Source impact sets from the CLL `impacted` flag instead of the broader canvas `impactedNodeIds`, with `impactingNodeIds` bridging the cases CLL deliberately omits (`partial_breaking` source nodes, `removed`). Fixes self-modified-but-non_breaking parents being wrongly marked. - Section-header amber chip becomes a toggle: click to filter the side to impacted models only. Per-side, with directional tooltips and pagination reset. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
The canvas already shows the impacted (amber) style on unchanged nodes
that the CLL flags as `impacted = true`. The Lineage tab's status dot
ignored that and rendered them with the neutral "unchanged" gray —
visually inconsistent with the graph (e.g. customer_order_pattern in
the customers panel).
`StatusDot` and `FocusCard` now reuse `cllChangeStatusColors.impacted`
when status is unchanged AND the node carries `cll.impacted = true`. The
focus card's status badge text follows ("impacted" instead of
"unchanged"). The dot exposes a `data-status` attribute for testing.
Also drop `ImpactAnalysisFocusOutsideSet` Storybook variant — it
rendered identically to `Default` and the behavior stays covered by the
unit test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
…im comments Unify Lineage tab impact marks (rail, arrow, chip, dot) on cllChangeStatusColors.impacted so they match the canvas "!" badge and impacted node border, replacing rgb(255 173 21) which the canvas never actually used. Mirror schema's --schema-badge-impacted-* palette for the chip; active state uses a deeper amber so white text stays legible. Also strip internal issue identifiers and tighten doc comments to keep only the non-obvious "why" (partial_breaking / removed propagation, focus-in-chain gating, no downstream→upstream bleed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
Cleanups to the Lineage tab impact-mark code introduced in this branch:
- Extract effectiveStatus / colorForEffective helpers — single source for
the "unchanged + cllImpacted → impacted" mapping that was duplicated
across StatusDot, getNodeStatusColor, and FocusCard.
- Split the impact chip into ChipButton (interactive) and ChipBadge
(display-only), removing the polymorphic component={x ? "button" :
"span"} pattern and its dangling type="button" attribute.
- Flatten the triple-nested chipTitle ternary into a getChipTitle
helper with early returns.
- Rename DirectRow props for distinct intent: impacted →
decorateAsImpacted (drives the rail/tint/arrow), cllImpacted →
dotImpacted (drives the dot color).
- Add a comment marking the trailing arrow icon as direction-agnostic
(the tooltip carries direction).
Also fix amber legibility on light backgrounds: the canvas amber
rgb(252 211 77) reads fine as a filled shape (dot, rail, chip bg) but
fails contrast as a thin-stroke icon or small text on white. Add an
impactedTextColor() helper (deeper amber rgb(146 64 14) in light mode,
light yellow in dark mode) and apply it to:
- the trailing impact-mark arrow icon in DirectRow
- the FocusCard "Impacted" pill text and border (when status is
impacted)
The other impact visuals — left rail, dot, chip background — keep the
canvas amber since brightness reads correctly on filled shapes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
…le fallback Extract NodeViewOss's CLL→impact-sets transformation into computeLineageTabImpactSets so the partial_breaking/removed bridge has direct unit coverage — previously the only tests passed the sets in already-built, leaving silent-regression risk if someone simplified the branching to `if (n.impacted) ...` and dropped the bridge. Also simplify getChipTitle: it was typed `string | undefined` only to support a non-existent `interactive=false` caller, with the call site papering over it via `?? label`. Drop the parameter and tighten the return type. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
Move the impact chip's bg/fg/active-accent constants out of LineageTabContent into lineage/styles.tsx as cllImpactedAccent / cllImpactedBadgeBg / cllImpactedBadgeFg. Light accent and dark badge fg reference cllChangeStatusColors.impacted directly; badge backgrounds compose alpha onto private hue triplets via space-separated rgb() syntax. Update schema/style.css's cross-file sync note to point at the new exports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
802a11a to
91867b2
Compare
The chip went from non-interactive (initial commit) to a toggle (9ae2402) and was later split into ChipButton/ChipBadge to clean up a polymorphic `component={x ? "button" : "span"}` pattern (d8efd07). The display-only ChipBadge survived the split, but both SectionHeader call sites always pass `onToggleOnlyImpact`, leaving the badge branch unreachable. Drop ChipBadge, tighten `onlyImpact` and `onToggleOnlyImpact` to required on the prop type, and inline the chip render. Removes the shared `data-testid="lineage-impact-chip"` between two component variants and the `!!onlyImpact` coercion that only existed to bridge the optional. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Wei-Chun, Chang <wcchang@infuseai.io>
…ges-on-direct-upstreamdownstream
…ges-on-direct-upstreamdownstream
Code Review: PR #1352Reviewed commit: Validation ResultsPass A: Correctness & Logic — PASSTraced the impact-set wiring end-to-end:
No logic inversion, no off-by-one, no null deref, no boundary violation. Pass B: Security — PASSUI-only feature. No new API surface, no user-controlled URLs, no Pass C: Cross-Reference Consistency — PASS
Pass D: Error Handling & Edge Cases — PASS
Pass E: Test Coverage & Quality — PASS
Pass F: Diff-Specific Checks — PASS
Pass H: Async/Concurrency — PASSNo async code in any changed file. No promises, no Verification Results
Verdict: GOAll validation passes clean. No BLOCKERs, no ISSUEs. Notes
What I could not verify
What I looked for and did not find
|
gcko
left a comment
There was a problem hiding this comment.
Claude Code Review: No critical issues found.
gcko
left a comment
There was a problem hiding this comment.
Claude Code Review: No critical issues found.
PR checklist
What type of PR is this?
feat / enhancement (UI)
What this PR does / why we need it:
Brings the canvas Impact Analysis signal into the Model Detail panel's Lineage tab so reviewers don't have to cross-reference rows against the graph.
When the focused model and a direct neighbor are both in the impact chain, the row is decorated with a 3-px amber left rail, an 8% amber background tint, and a trailing amber arrow icon (tooltip: "Impacts this model" / "Impacted by this model" depending on direction). The section header gains an amber count chip ("N impacting" / "N impacted") that doubles as a per-side toggle: click it to filter that rail to only impacted models; click again to restore. The status dot also picks up the impacted amber on unchanged-but-impacted neighbors so the panel reads consistently with the canvas border.
The two impact sets are derived directly from CLL —
impactedNodeIdsmirrors the canonicalcll.impacted = trueflag (used for the downstream rail and dot color), andimpactingNodeIdsadds the two cases CLL deliberately omits despite propagating impact (partial_breakingmodified nodes andremovednodes). This avoids the bug where a self-modified-but-non_breakingparent (e.g. an stg_* that adds an unused column) would be wrongly marked as impacting downstream.Canvas coloring is untouched — the existing
LineageViewContext.impactedNodeIdscontinues to drive the amber border.Which issue(s) this PR fixes:
DRC-3344
Special notes for your reviewer:
LineageTabContentaccepts both impact sets as optional props, so existing tests and Storybook mounts that don't wrapLineageViewProviderkeep rendering without marks.ImpactAnalysisActive,ImpactAnalysisPartialBreaking, andImpactAnalysisDense(the redundant focus-outside-set variant was dropped — covered by unit test).Does this PR introduce a user-facing change?:
The Model Detail panel's Lineage tab now mirrors the canvas Impact Analysis: direct upstream and downstream rows that participate in the impact chain are marked with an amber rail, tint, arrow, and tooltip; section headers carry a clickable amber count chip that filters the side to only impacted models.