feat(lineage): add Body Changes view mode to filter config-only changes#1268
feat(lineage): add Body Changes view mode to filter config-only changes#1268even-wei wants to merge 12 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests.
... and 4 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Add a new "Body Changes" mode to the lineage view Mode dropdown that uses state:modified.body + state:modified.macros + state:modified.contract selectors. This filters out config-only YAML changes (tags, descriptions, deprecation dates, etc.) while keeping data-impacting changes visible. The existing "Changed Models" and "All" modes remain unchanged. Resolves DRC-3047 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: even-wei <evenwei@infuseai.io>
- Add missing body_changes to LineageView.tsx and LineageDiffView.tsx types - Handle body_changes in Cloud LineageView node filtering (was falling through to "all") - Update stale comments in run.ts, LineageViewTopBar docstring, and 3 test files - Add Body Changes radio to dropdown assertion in existing test - Add interaction test for switching to body_changes mode Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: even-wei <evenwei@infuseai.io>
062059a to
9fbdd18
Compare
Cover the body_changes branch in select_nodes to fix patch coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: even-wei <evenwei@infuseai.io>
Code Review: PR #1268Reviewer: Claude Code Review (adversarial) Validation ResultsPass A — Correctness & Logic — FAILISSUE —
} else if (
viewOptions?.view_mode === "changed_models" ||
viewOptions?.view_mode === "body_changes"
) {
// Changed models or body changes (filtering done server-side via selector)
selectedNodeIds = lineageGraph.modifiedSet;
}
Consequence: a user who saves a Lineage Diff check while in Body Changes mode will see the same node set as a Changed Models check (config-only YAML edits included), defeating the feature's purpose for that surface. The selector value is preserved on the wire, but the rendered graph isn't. Either:
NOTE — Empty-state guard missing for if (viewMode === "changed_models" && !lineageGraph.modifiedSet.length) {
return <LineageViewNoChanges ... />;
}For Pass B — Security — PASSNo new endpoints, no new authn/authz boundaries, no PII surfaces. The selector strings are static (not user-controlled). Pass C — Cross-Reference Consistency — PASSThe Verified: existing Pass D — Error Handling — PASS
Pass E — Test Coverage — PASS with one gap
Gap: No test exercises the case the feature is for — a project where some models have body changes and others have config-only changes — to assert that Pass F — Diff-Specific Checks — PASS
Pass G — Performance — PASSThe selector compiles once per Pass H — Async/Concurrency — N/ANo async surface change. Verification Results
Verdict: NO-GOIssues
Notes
What I could not verify
What I looked for and did not find
PR is in draft. Mark ready-for-review only after addressing the LineageView filtering branch (or documenting why |
- LineageView.tsx: drop body_changes from the modifiedSet fallback (it rendered config-only changes too); document that saved body_changes checks must carry resolved node_ids. - LineageViewOss.tsx: persist filteredNodeIds on body_changes saved Lineage Diff checks so the presentational LineageView has the right set; add an empty-state guard for body_changes when the server-side selector returns nothing. - test_selector.py: add a config-only model (same raw_code, differing unrendered_config.meta) and assert body_changes is a strict subset of changed_models. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: even-wei <evenwei@infuseai.io>
…-changes-mode Signed-off-by: even-wei <evenwei@infuseai.io>
2b29bd8 to
04dfdb2
Compare
…(DRC-3047) Regression coverage for the two NO-GO frontend fixes from the 2026-04-29 self-review of PR #1268, now hardened with explicit tests: - saved-check replay: when viewOptions carries explicit node_ids in body_changes mode, LineageView must honor that subset and NOT fall back to lineageGraph.modifiedSet (which includes config-only nodes). - no client-side body_changes fallback: body_changes without node_ids must leave selectedNodeIds undefined, since the filter is resolved server-side. Falling back to modifiedSet would defeat the feature. - empty-state: body_changes with an empty filter result renders the friendly "No nodes match the current filter criteria." placeholder. - regression guard: changed_models still falls back to modifiedSet. Pairs with the code fixes already in 8cffa99 (round-2 review fix). Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: even-wei <evenwei@infuseai.io>
…C-3047) Seven captured screenshots paired with the PR Verification section: - SS-1 mode dropdown open showing Body Changes alongside Changed Models / All - SS-2 Mode=All (5 modified models + upstream staging on jaffle_shop fixture) - SS-3 Mode=Changed Models (default — both body and config-only mods present) - SS-4 Mode=Body Changes (4 nodes, config-only `orders` excluded) - SS-5 paired SS-3 / SS-4 with `orders` annotated as the excluded config-only model - SS-6 saved Lineage Diff check titled "Lineage diff of 4 nodes" — replay renders the 4-node subset, NOT the 5-node modifiedSet (validates the saved-check filtering fix from commit 8cffa99) - SS-7 Body Changes empty-state ("No change detected") for a branch with only config-only YAML edits — validates the LineageViewOss guard from commit 8cffa99 Fixture: integration_tests/dbt with a 1-line body change in customers.sql plus a description/meta-only change in schema.yml `orders` model. Verified via /api/select: changed_models returns 5 nodes, body_changes returns 4, and with the body change reverted body_changes returns 0 → empty-state. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: even-wei <evenwei@infuseai.io>
PR checklist
What type of PR is this?
Feature
What this PR does / why we need it:
Adds a new "Body Changes" mode to the lineage view Mode dropdown. This mode uses
state:modified.body,state:modified.macros, andstate:modified.contractselectors to filter out config-only YAML changes (tags, descriptions, deprecation dates, warehouse, materialization, etc.) while keeping data-impacting changes visible.This reduces noise for users whose PRs touch YAML config without changing SQL logic — a pain point raised by customers (see Slack thread in #customer-super).
Which issue(s) this PR fixes:
Resolves DRC-3047
Special notes for your reviewer:
1+state:modified+) and "All" modes remain unchangedchanged_modelsis still the default for UI and MCPrecce summarycommand is not changed in this PR; it already excludes config-only changes via checksum comparison. A follow-up issue can add full selector parity if neededimpact_analysistool already uses this same selector pattern (state:modified.body+ state:modified.macros+ state:modified.contract+)Does this PR introduce a user-facing change?:
Yes — new "Body Changes" option in the lineage view Mode dropdown that filters to only SQL body, macro, and contract changes.
Verification
Reproduction
Fixture:
integration_tests/dbtwith a 1-line body change incustomers.sql(+ where customer_id > 0) plus a description andmetachange on theordersmodel inschema.yml. Run:Both
customersandordersare flaggedmodified(change_status=modified). The body_changes selector must excludeorders.Screenshot evidence
All committed under
docs/screenshots/drc-3047/.orders(config-only) andcustomers(body)ordersexcludedorderscircled red on left, dashed green on right marking its absenceQuantitative annotations (verified via
/api/select)1+state:modified+ordersexcluded)1+state:modified.body+ state:modified.macros+ state:modified.contract+Tests
uv run pytest tests/adapter/dbt_adapter/test_selector.py tests/tasks/test_lineage.py tests/tasks/test_row_count.py tests/tasks/test_schema.py→ 25 passed, including non-degeneratebody_changesfixture (customers_6config-only excluded;body_ids < changed_idsasserted) — self-review NO-GO Add diffview in web server #3 fixcd js && pnpm vitest run→ 3724 passed | 5 skipped, including 4 new regression tests inLineageView.test.tsxcovering saved-check replay (explicitnode_idshonored), no-fallback semantics forbody_changeswithoutnode_ids, body_changes empty-state, and the changed_models regression guardpnpm lint→ clean;pnpm type:check→ cleanSelf-review NO-GO items — all resolved
LineageView.tsxsaved-check filter would short-circuitbody_changestomodifiedSetLineageViewOss.addLineageDiffCheckpersists resolvedfilteredNodeIdson save;LineageViewdropsbody_changesfrom themodifiedSetfallbackbody_changeszero resultbody_changesbranch alongside thechanged_modelsempty-state path inLineageViewOsstest_selector.pyaddscustomers_6config-only model (sameraw_code, differingunrendered_config.meta); assertsbody_ids < changed_idsRollback / risk
changed_modelsremains the default for UI and MCP. New mode is opt-in.state:modified.body, fallback isview_mode: "all"— user sees full graph instead of error (existing try/except atLineageViewOss.tsx:514-538).🤖 Generated with Claude Code