Skip to content

#404 — feat(render): PR-scope lineage mini-DAG at the report top (EXPERIMENTAL) + click→selector - #407

Merged
cmbays merged 2 commits into
mainfrom
render-404-prscope-minidag
Jun 14, 2026
Merged

cmbays merged 2 commits into
mainfrom
render-404-prscope-minidag

Conversation

@cmbays

@cmbays cmbays commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

Closes #404

Renders the PR-scope lineage mini-DAG at the top of the report (epic #352, Slice C): the focused cross-model subgraph showing the models the PR modified (emphasized), the connectors between them (a quiet tier), and the deleted models (ghosts), each with its lines ± chip. Clicking a node selects that model in the report's existing selector.

What landed

  • Run-loop wiring (src/cli/mod.rs): gather_pr_dag builds the PrDag per scope arm and populates per-node line counts — pr-diff arm from the diff hunks, baseline arm from raw_code old→new (plus the new/deleted sets) — then threads an Option<PrDagPayload> into render. The experiment gate is the single construction source at the top of gather_pr_dag (the gather_macro_lens precedent).
  • Render (render.rs + templates/report.html): a PrDagPayload render view (graph + per-state descriptor counts + a size-bound collapsed flag, cap 48 nodes) rides the JSON payload and drives a server-rendered descriptor + a static Mermaid host. The graph paints client-side from DATA.pr_dag.graph via a gated inline script (Mermaid — the static default engine, one engine per page), so the OFF case emits zero bytes.
  • Click→selector (gated inline script): clicking a node reuses the existing change.cuteDbt contract on #model-select and scrolls the selection into view. A settings-panel viewer toggle shows/hides the panel.
  • EXPERIMENTAL gate: new Experiment::PrScopeMiniDag (id pr-scope-mini-dag), default OFF. Byte-identity preserved for the default goldens.
  • Dogfood: a synthetic connector-path manifest (stg_orders → int_order_items → fct_orders; stg + fct modified, int the connector) + patch + the new examples/prdiff-minidag-report.html golden (experiment ON), wired into the byte gate, the synthetic-only fixture manifest, the resource-ref + zero-egress gates, and a headless test asserting the mini-DAG renders and a node click selects the model.

Render review

The reviewable artifact is examples/prdiff-minidag-report.html (open it directly). It shows the connector path with stg_orders (+1/-1) and fct_orders (+1/-1) emphasized and int_order_items as the quiet connector between them.

Gates

cargo fmt --check, clippy --all-targets --locked -D warnings, cargo nextest run (2209 passed), cargo test --test bdd (226 scenarios), headless zero-egress + toggle (incl. the new click→select assert), cargo doc -D warnings, cargo deny check, resource-ref lint, golden byte-identity — all green. The default OFF goldens (jaffle-shop, playground) stay byte-identical; only the all-experiments diff-showcase golden gains the mini-DAG (1 node).

🤖 Generated with Claude Code


Open in Stage

Summary by CodeRabbit

Release Notes

  • New Features

    • Added PR-scope lineage mini-DAG visualization to reports, displaying modified and removed nodes with line-count details; users can click nodes to select corresponding models; includes an experimental toggle control and automatic collapse for large graphs.
  • Documentation

    • Added example report showcasing the new mini-DAG visualization.
  • Tests

    • Enhanced test coverage with new fixtures and rendering tests for mini-DAG functionality.

…AL) + click→selector

#404 (epic #352, Slice C) — render the focused cross-model lineage subgraph
at the top of the report: the models the PR modified (emphasized), the
connectors between them (a quiet tier), and the deleted models (ghosts), each
with its lines ± chip. Clicking a node selects that model in the report's
existing <select>.

Run-loop wiring (src/cli/mod.rs): `gather_pr_dag` builds the PrDag for the
in-scope set per scope arm (pr-diff: changed_models + diff-hunk line counts;
baseline: StateComparator modified + raw_code old→new line counts, plus the
new/deleted sets), populates each node's lines ±, and threads an
`Option<PrDagPayload>` into render. The single experiment gate lives at the top
of `gather_pr_dag` (the gather→render single construction source, the
macro-lens precedent).

Render (render.rs + templates/report.html): a new `PrDagPayload` render view
(graph + per-state descriptor counts + size-bound `collapsed` flag, cap 48
nodes) rides the JSON payload and drives a server-rendered descriptor + static
Mermaid host. The mini-DAG paints client-side from `DATA.pr_dag.graph` via a
GATED inline script (Mermaid — the static default engine, one engine per page),
so the OFF case emits zero bytes and the default goldens stay byte-identical.
Click→select reuses the #91 `change.cuteDbt` contract; a viewer toggle row in
the settings panel shows/hides the panel.

EXPERIMENTAL gate: new `Experiment::PrScopeMiniDag` (id `pr-scope-mini-dag`),
default OFF. Byte-identity verified for jaffle-shop + playground (default OFF);
the all-experiments diff-showcase golden gains the mini-DAG (1 node); the
macro-heavy + seed-showcase goldens are unchanged (their pr-diffs modify no
model, so the mini-DAG is None).

Dogfood: a synthetic connector-path manifest (stg_orders → int_order_items →
fct_orders; stg + fct modified, int the connector) + patch + the new
`examples/prdiff-minidag-report.html` golden (experiment ON), wired into the
example-report-check byte gate (ci.yml + report-preview.yml), the
synthetic-only fixture manifest, the resource-ref + zero-egress gates
(COMMITTED_EXAMPLES), and a headless test asserting the mini-DAG renders and a
node click selects the model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Implements the PR-scope lineage mini-DAG feature (#404, Slice C): adds the PrScopeMiniDag experiment gate, domain helpers (DEFAULT_PR_DAG_NODE_CAP, populate_line_counts), a PrDagPayload render struct wired through ReportPayload and render_report_with_externals, a Mermaid-backed HTML panel with click→model-select binding, CLI orchestration stages, and a synthetic three-model fixture set with headless and golden CI coverage.

Changes

PR-scope lineage mini-DAG (Slice C)

Layer / File(s) Summary
Domain: experiment variant, DAG node-cap, line-count population, and re-exports
src/domain/experimental.rs, src/domain/pr_dag.rs, src/domain/mod.rs
Registers Experiment::PrScopeMiniDag (wire id pr-scope-mini-dag), adds DEFAULT_PR_DAG_NODE_CAP = 48, introduces populate_line_counts to overwrite per-node LineDelta values, and expands public re-exports to include the new constant and all line-derivation helpers.
explore.rs: lineage_vertex_type helper extraction
src/adapters/explore.rs
Extracts a private lineage_vertex_type helper from focused_typed_node_map that maps model/snapshot/seed to LineageNodeType and returns None for all other resource types; adds unit test coverage.
Renderer: PrDagPayload struct, ReportPayload field, and function signature
src/adapters/render.rs
Adds PrDagPayload with from_graph (computing descriptor counts and collapsed flag); extends ReportPayload with pr_dag: Option<PrDagPayload>; updates ReportTemplate, build_payload_with_externals, render_report, and render_report_with_externals; patches all existing test payload literals with pr_dag: None; adds PrDagPayload::from_graph tests.
HTML template: mini-DAG panel and settings toggle
templates/report.html
Adds a pr_dag-gated "PR scope lineage" panel with a Mermaid flowchart rendered from #cute-dbt-data, keyboard/click node interactions that dispatch change.cuteDbt on #model-select, a viewer toggle checkbox, and a matching Experimental settings row.
CLI: gather_pr_dag pipeline and render threading
src/cli/mod.rs
Adds gather_pr_dag, pr_dag_scope_sets, and populate_pr_dag_line_counts internal functions; threads pr_dag.as_ref() from execute_report through to render_report_with_externals; refactors gather_external_fixtures_with_reader into external_fixtures_for_test.
Synthetic fixtures: prdiff-minidag manifest, patch, and source SQL/YAML
tests/fixtures/prdiff-minidag-current.json, tests/fixtures/prdiff-minidag-pr-diff.patch, tests/fixtures/prdiff-minidag-source/..., tests/fixtures/MANIFEST.toml
Introduces the prdiff-minidag synthetic fixture set: a v12 manifest (stg_orders → int_order_items → fct_orders), a two-model PR diff patch, five working-tree SQL/YAML source files, and matching MANIFEST.toml provenance records.
Tests, CI, and golden example wiring
tests/headless_toggle.rs, tests/common/mod.rs, .github/workflows/ci.yml, .github/workflows/report-preview.yml, examples/README.md
Adds the headless PR-scope mini-DAG test harness and headless Chrome test; updates all existing render_report_with_externals call sites with the new None argument; registers prdiff-minidag-report.html in COMMITTED_EXAMPLES; extends CI matrices; adds examples README docs.

Sequence Diagram(s)

sequenceDiagram
  participant User as User (browser)
  participant HTML as report.html panel
  participant Mermaid as window.mermaid
  participant Select as `#model-select`

  rect rgba(70, 130, 180, 0.5)
    note over HTML,Mermaid: DOMContentLoaded — mini-DAG init
    HTML->>HTML: parse `#cute-dbt-data` JSON → pr_dag.graph
    HTML->>Mermaid: mermaid.render(flowchart definition)
    Mermaid-->>HTML: SVG injected into .pr-minidag-canvas
  end

  rect rgba(100, 160, 100, 0.5)
    note over HTML,Select: Node click interaction
    User->>HTML: click g.node (e.g. fct_orders)
    HTML->>Select: dispatch change.cuteDbt (or change)
    Select-->>HTML: model detail panel updates
  end

  rect rgba(180, 100, 80, 0.5)
    note over HTML: Viewer toggle
    User->>HTML: uncheck `#settings-prdag-input`
    HTML->>HTML: hide .pr-minidag-panel
  end
Loading
sequenceDiagram
  participant CLI as execute_report
  participant Gather as gather_pr_dag
  participant Domain as compute_pr_dag + populate_line_counts
  participant Renderer as render_report_with_externals
  participant Template as ReportTemplate

  CLI->>Gather: manifest, scope, experiments
  Gather->>Domain: pr_dag_scope_sets → (modified, new, removed)
  Domain-->>Gather: PrDagGraph topology
  Gather->>Domain: populate_pr_dag_line_counts
  Domain-->>Gather: PrDagGraph with line deltas
  Gather-->>CLI: Some(PrDagPayload::from_graph(...))
  CLI->>Renderer: pr_dag: Some(&PrDagPayload)
  Renderer->>Template: ReportPayload { pr_dag: Some(...) }
  Template-->>Renderer: HTML with mini-DAG panel
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • breezy-bays-labs/cute-dbt#357: This PR extends src/domain/pr_dag.rs with DEFAULT_PR_DAG_NODE_CAP and populate_line_counts, then wires the PrDagGraph through PrDagPayload::from_graph and template bindings — directly building on the core compute_pr_dag domain implementation landed in #357.
  • breezy-bays-labs/cute-dbt#334: Both PRs extend ReportPayload and render_report_with_externals in src/adapters/render.rs with a new optional field and matching template wiring, using the same integration seam.
  • breezy-bays-labs/cute-dbt#282: Both PRs touch src/adapters/explore.rs for typed lineage node classification via LineageNodeType — #282 expanded the typed node structure that this PR's lineage_vertex_type helper refactors against.

Suggested labels

type:feature

🐇 A mini-DAG blooms atop the report today,
Three models linked — stg, int, fct all in play!
Connectors hum, the modified nodes glow bright,
Click a node, the selector snaps just right. ✨
EXPERIMENTAL-gated, the bunny hops with glee —
Line counts, collapse, and mermaid — pure artistry! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding PR-scope lineage mini-DAG rendering with click-to-selector functionality as an experimental feature.
Linked Issues check ✅ Passed All acceptance criteria from #404 are met: cross-model lineage rendering at report top with modified/connector/deleted distinction [#404], per-node line counts [#404], click-to-select model integration [#404], EXPERIMENTAL gate with byte-identity preservation [#404], size-bound collapse at 48 nodes [#404], and paired synthetic dogfood fixture with headless test validation [#404].
Out of Scope Changes check ✅ Passed All changes are scoped to #404 acceptance criteria: mini-DAG rendering, experimental gating, template bindings, CLI wiring, test fixtures, and workflow configuration. No unrelated refactoring or auxiliary features detected beyond the scope of PR-scope mini-DAG visualization.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch render-404-prscope-minidag

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

📄 Rendered report preview

All golden examples regenerated cleanly.

🟡 Golden examples

Committed to examples/ and byte-identity gated — the canonical reports contributors and consumers browse. Stable across PRs.

Report View Download
jaffle-shop-report.html ▶ Open ↗ ⬇ Download
macro-heavy-report.html ▶ Open ↗ ⬇ Download
prdiff-minidag-report.html ▶ Open ↗ ⬇ Download
playground-report.html ▶ Open ↗ ⬇ Download
diff-showcase-report.html ▶ Open ↗ ⬇ Download
seed-showcase-report.html ▶ Open ↗ ⬇ Download

🐶 Live dogfood preview

This PR doesn't touch dbt-project/, so there's no live dogfood preview.

🧭 Explore preview

The two-page cute-dbt explore explorer — dag.html (model lineage) + tests.html (unit-test viewer). Same golden/live split as the report.

🟡 Golden explore

The committed examples/explore/ playground golden (the full synthetic playground manifest). Byte-identity gated in Example report check. Stable across PRs.

Page View Download
explore/dag.html ▶ Open ↗ ⬇ Download
explore/tests.html ▶ Open ↗ ⬇ Download

🐶 Live explore

This PR doesn't touch dbt-project/, so there's no live explore preview.

▶ Open ↗ opens the report or explorer in your browser in one
click — published to this repo's GitHub Pages under
/pr-407/.
⬇ Download fetches the same self-contained HTML as a workflow
artifact (auth-gated; works fully offline). Either way the report
makes zero external resource requests.

The Pages preview may take ~1 min to update after this comment
posts. On PRs from forks the Open link is unavailable (read-only
token) — use Download.

Alternative: GitHub CLI
# gh CLI >= 2.63 extracts into ./report-preview-playground/.
gh run download 27500195705 -R breezy-bays-labs/cute-dbt -n report-preview-playground
open report-preview-playground/playground-report.html

Posted by report-preview.yml for 6862bfc3212711322303e2d48e0aeab565e29bd3. Affordance only — never blocks merge.

…xplore helpers (#404)

The `crap4rs scorecard` gate on PR #407 was RED because
`PrDagPayload::from_graph` (render.rs, strict-keyed <=15) scored CRAP
30.00: CC 5 at 0.0% line coverage. Its only caller is a headless test,
which `cargo llvm-cov nextest` does not count. Add four `#[cfg(test)]`
unit tests building a `PrDagGraph` and asserting the payload shape
(state->tier classification, connector-flag precedence over Deleted,
the strict `> cap` collapse boundary, empty-graph zeros, graph carried
verbatim). from_graph now CC 5 / cov 100.0% / CRAP 5.00.

Founder-flagged hygiene (under the default <=25, non-gating) addressed
via behavior-preserving extraction:

- explore.rs `focused_typed_node_map` 17.77 -> 13.15: pull the
  resource_type -> LineageNodeType classification into a named
  `lineage_vertex_type` helper (CC 2, cov 100%), with a direct unit
  test over every vertex / non-vertex arm.
- cli/mod.rs `gather_external_fixtures_with_reader` 15.01 -> 8.02:
  pull the per-test given/expect assembly into `external_fixtures_for_test`
  (CC 5, cov 100%); the gather loop is now a thin per-test driver.

`execute_report` left alone (CRAP 17.00, CC 17, cov 99.1%): it is the
documented linear composition root carrying `#[allow(too_many_lines)]`;
its CC is one named gather/diff-arm step per branch and the prompt
flags it as do-not-destabilize. Under the default gate, so non-gating.

Scorecard: 0 above threshold (25) | worst 17.0 | PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cmbays
cmbays merged commit 3f6dda7 into main Jun 14, 2026
42 of 43 checks passed
@cmbays
cmbays deleted the render-404-prscope-minidag branch June 14, 2026 13:29
@cmbays

cmbays commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

Merged to main (3f6dda7), closes #404.

What shipped: PR-scope lineage mini-DAG at the report top (EXPERIMENTAL-gated via Experiment::PrScopeMiniDag) + click→selector. Final commit added the CRAP fix: PrDagPayload::from_graph 30.00→5.00 (4 behavioral unit tests — state→tier classification, is_connector branch precedence, the strict > cap boundary, verbatim graph carry), plus two behavior-preserving helper extractions (lineage_vertex_type 17.77→13.15, external_fixtures_for_test 15.01→8.02). execute_report left at 17.0 (composition root, under default gate, do-not-destabilize).

Gate: crap4rs exits 0; all 22 required checks green. Engineering-cleared SHIP (already adversarially gated last session; the CRAP delta was orchestrator-verified — extractions behavior-preserving by construction, tests assert real invariants, not coverage-padding).

Disposition: founder-authorized ship of the mini-DAG arc (#352). Experiment OFF by default → shipping report byte-identical.

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.

render: PR-scope mini-DAG at the report top + EXPERIMENTAL gate + click→selector + dogfood (#352 Slice C)

1 participant