Skip to content

DRC-3813: impact outranks additive in CLL graph-badge precedence#1468

Draft
danyelf wants to merge 3 commits into
mainfrom
feature/drc-3813-badge-precedence
Draft

DRC-3813: impact outranks additive in CLL graph-badge precedence#1468
danyelf wants to merge 3 commits into
mainfrom
feature/drc-3813-badge-precedence

Conversation

@danyelf

@danyelf danyelf commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Note: this is Claude being really enthusiastic about the issue MERELY being rank. From a design POV, the real issue is that a local change (e.g. a column-level additive) is both important to see -- but also should not hide the fact that it's impacted from a parent.

Background (for a reader with no context)

In Recce's new column-level-lineage (CLL) experience, each node in the lineage graph shows a small badge summarizing how that model was affected by a change. The relevant two here:

  • 🟢 ADD ("additive") — the model added a column; existing rows/columns are unchanged. Benign.
  • 🟠 COLUMN ("column-impacted") — a column this model depends on changed upstream, so this model is impacted and worth reviewing.

Which badge to show is decided by classifyGraphBadge in js/packages/ui/src/components/lineage/wholeModelTreatment.ts.

The problem

classifyGraphBadge checked the node's own change category before checking whether it was impacted by an upstream change:

if (changeCategory === "non_breaking")  return "additive";      // ← checked first
if (changeCategory === "partial_breaking") return "column-changed";
if (isImpacted) return "column-impacted";                        // ← too late

So a node that is genuinely impacted upstream, but whose own SQL only added something (category non_breaking), got the benign green ADD badge — hiding the more important fact that it's impacted. The backend had already correctly flagged the node as impacted; this was purely a presentation bug in the badge ordering. (Only non_breaking was affected — see the precedence table below.)

Concrete repro

  • PARENT model redefines a column: c1 changes from id to id || lastname.
  • CHILD model: select id, name from parent where length(parent.c1) < 10 — it filters on c1 but never selects it, and its own SQL is otherwise unchanged.

CHILD is impacted (the column it filters on changed), but because its own change is merely additive/non-breaking:

Badge before Badge after
CHILD node 🟢 ADD (green, "additive") — misleading 🟠 COLUMN (amber, "column-impacted") — correct

Here is the same CHILD node rendered with identical inputs — the fix reverted (left) vs applied (right):

Before/after: green ADD badge vs amber COLUMN badge on the same node

The fix

Move the isImpacted check up by one line so impact outranks additive, while a genuine own-column change (partial_breaking) still outranks impact:

if (changeCategory === "partial_breaking") return "column-changed";
if (isImpacted) return "column-impacted";
if (changeCategory === "non_breaking")  return "additive";

Net precedence: column-changed (own change) > column-impacted (impacted) > additive (own additive). This preserves the file's documented "changed-wins" doctrine — a node's own change still outranks being impacted — but a harmless additive change no longer masks the impact signal.

Precedence across all four change categories combined with isImpacted: true (only non_breaking was wrong):

change_category before after was it a bug?
breaking (short-circuited earlier) same no
non_breaking additive (green) column-impacted (amber) yes — this bug
partial_breaking column-changed column-changed no — intentional
unknown column-impacted column-impacted no

Verification

  • Strict TDD: 3 combined-case tests (classifier light+dark in wholeModelTreatment.test.ts via the exported pickGraphBadge, plus a <LineageNode> render assertion in LineageNode.test.tsx) committed red first, green after the reorder. Reverting only the one-line reorder reddens exactly those 3 and nothing else.
  • The four existing regression cases (additive-only, column-changed, column-impacted-only, whole-model short-circuit) stay green.
  • Full frontend suite 4045 passed / 5 skipped; Biome + type:check clean on all touched files.
  • Reproducible Storybook story LineageNode_ImpactedOutranksAdditive renders the CHILD repro through the real LineageNode, driving the before/after image above.

Frontend-only; backend node.impacted was already correct and is untouched. Distinct from the DRC-2891/380x lineage-extraction work (that's a different layer). Opening as draft — validated in the workflow; pending final review.

🤖 Generated with Claude Code

danyelf and others added 3 commits July 9, 2026 00:05
…edence (DRC-3813)

A downstream node that is backend-flagged impacted but whose own
change_category is non_breaking currently renders the green additive
badge instead of the amber column-impacted badge. Add the missing
combined case at both the classifier level (pickGraphBadge) and the
render level (LineageNode), red against unmodified source.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Danyel Fisher <danyel@gmail.com>
…-3813)

Under the new CLL experience, a downstream node the backend flagged
impacted but whose own change_category is non_breaking rendered a
misleading green additive badge instead of the actionable amber
column-impacted badge. classifyGraphBadge checked the node's own
change_category before its isImpacted flag.

Reorder so isImpacted is checked before the non_breaking->additive
line. New precedence: partial_breaking (own column change) > isImpacted
> non_breaking (own additive change). partial_breaking still outranks
impact per the changed-wins doctrine; only non_breaking yields.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Danyel Fisher <danyel@gmail.com>
Adds LineageNode_ImpactedOutranksAdditive — the PARENT/CHILD repro where
CHILD's own change is additive (non_breaking) but it is backend-flagged
impacted. Renders green ADD before the badge-precedence fix and amber
COLUMN after, giving a reproducible visual before/after.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Danyel Fisher <danyel@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant