Skip to content

feat(agent): add dbt-optimizer agent — 6-lane dbt project optimization with evals - #1092

Open
anandgupta42 wants to merge 19 commits into
mainfrom
feat/optimizer-agent
Open

feat(agent): add dbt-optimizer agent — 6-lane dbt project optimization with evals#1092
anandgupta42 wants to merge 19 commits into
mainfrom
feat/optimizer-agent

Conversation

@anandgupta42

@anandgupta42 anandgupta42 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #1091

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds dbt-optimizer, a 5th native primary agent that scans a dbt project for fixable issues and proposes targeted fixes with cost/impact reporting (the agent behind the planned Optimize workflow). Four parts:

1. Agent registration (agent.ts). Deny-by-default permission allowlist: read/analysis/finops tools allowed, edit and bash prompt per action, sql_execute_write denied. The deny is re-applied after the global user-config merge AND after the per-agent config merge — permission evaluation is last-match-wins, so without the second re-application agent."dbt-optimizer".permission.sql_execute_write: "allow" would have silently won (regression tests cover both paths). Named dbt-optimizer rather than optimizer because more optimizer agents are planned; no alias shim needed since nothing shipped under the old name.

2. Prompt (prompts/dbt-optimizer.txt). Encodes the taxonomy from docs/internal/2026-08-12-dbt-optimization-taxonomy-research.md: 6 detection lanes, an evidence-attribution ladder (invocation-ID/query-tag down to lineage-match, with confidence labeling), ROI-ranked triage, cost-honesty rules ("not estimable" is a valid answer; never invent dollar figures), a 4-phase loop that stops after scan for candidate selection, and an auto-fix vs propose-only boundary. Builder's self-review gains a dbt-scoped "Optimization handoff" nudge — primary agents are excluded from the task tool (task.ts filters mode !== "primary"), so the nudge is the only build-time bridge and auto-delegation of cost-incurring scans is deliberately NOT wired.

3. Verification-tool fixes. Three latent bugs in existing tools the agent's core promises depend on, found during review: the rewrite verify gate trusted equivalent: true even when the engine said decidable: false (now UNDECIDABLE = unproven, everywhere it surfaces); sql_explain analyze:true executes the statement on Postgres/MySQL/DuckDB/Trino and had no statement-class guard (now blocked for anything non-read-only, including SELECT ... INTO); the sql_diff wrapper read response fields the native handler never returns, so every comparison reported "identical".

4. Evals. Tier 1 (CI): 20 deterministic tests asserting the prompt's non-negotiable invariants (whitespace-normalized so reflow doesn't break them) plus an evidence-chain suite proving each planted fixture issue is genuinely detectable. Tier 2 (opt-in): a live eval that runs the compiled binary against a 7-model DuckDB fixture with 6 planted issues (incremental candidate, dead model, SELECT * propagation, ORDER BY, verbatim-duplicated CTE ×3, untested model) and grades deterministically — ≥4/6 recall with directional signal phrases, exit-code check, and a tree-snapshot proving the scan modified/removed/added nothing. Answer key lives outside the scanned directory.

How did you verify your code works?

  • 230 tests green across the 9 affected files (agent permissions incl. both override-bypass regressions, carry-forward guards, tool fixes, prompt contract, fixture evidence chain); tsgo --noEmit clean; upstream marker check clean (--markers --base main --strict); oxlint 0 errors on changed files.
  • Four external review rounds (Codex): plan review, full-diff review, and two focused verification passes — findings (permission bypass, undecidable gate, EXPLAIN ANALYZE execution, sql_diff contract, eval grading false-positives, contradictory planted issue) were each fixed with regression tests.
  • NOT verified: the tier-2 live eval has not been run against a live model yet (it is opt-in and needs a compiled binary + API key); the finops-dependent scan lanes are untested against a real warehouse — the fixture exercises the static lanes only.

Screenshots / recordings

Not a UI change — the agent appears in the existing Tab ring/agent list.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

🤖 Generated with Claude Code


Summary by cubic

Adds the dbt-optimizer agent for six‑lane dbt project scans with evidence‑backed fixes, and strengthens SQL, path, and permission safety. Previously, EXPLAIN ANALYZE and equivalence gates could execute or misclassify writes, built‑ins could bypass deny‑by‑default exposure, session/persisted approvals could override denies, and path‑taking tools could read outside the project; now analyze requires write approval with a safe fallback, UNDECIDABLE never counts as equivalent, denied tools are not exposed, approvals cannot flip a deny, and out‑of‑project reads are gated.

  • Agent and permissions: registers dbt-optimizer with deny‑by‑default; edit/bash ask; sql_execute_write is non‑overridable and re‑applied after config merges. Built‑in tool exposure honors denies via Permission.disabled (internal invalid exempt). Persisted “always allow” approvals and session‑supplied rules can no longer override configured denies (session rules merge before agent at ask time).

  • SQL/paths/analysis: sql_explain analyze mode requires write approval and uses a single‑pass masker for literals/comments/delimited identifiers (incl. bracket/dollar quoting and subscript cases); unsafe SQL falls back to estimated plans. sql_classify shares the masker, normalizes CR/CRLF, detects quoted side‑effect calls (including identifier‑quoted), and rejects write keywords hidden inside read‑shaped WITH/EXPLAIN/SELECT; statement‑form checks anchor at start. sql_diff uses LCS line diffs with context_lines and robust hunking, forwards schema_context/dialect, and reports equivalence_assessed/decidable; undecidable results never count as proven equivalent. All dbt readers and schema_path wrappers gate through external_directory, resolve paths relative to the project, read the same resolved path, and propagate permission rejections. Impact analysis is a true multi‑seed BFS by dbt unique_id (shortest depths, no self‑loops); affected tests counted by unique_id. Prompt encodes six lanes and build safety with a builder handoff nudge; deterministic prompt/evidence tests ship, plus an opt‑in DuckDB live eval with same‑candidate scoring. Docs surface reviewer/dbt-optimizer agents.

Written for commit 81ec904. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added a dbt-optimizer agent for evidence-based analysis and approval-gated fixes.
    • Added optimization guidance for materializations, SQL patterns, costs, testing, DAGs, and warehouse design.
    • Added support for SQL dialect context in comparison and rewrite workflows.
  • Bug Fixes

    • SQL comparisons now distinguish proven, different, and undecidable results.
    • Analyze operations reject unsafe SQL and require appropriate approval.
    • dbt tools now validate project and schema paths.
    • Protected warehouse writes and destructive operations from unauthorized access.
  • Documentation

    • Added guidance for agent scaling and dbt optimization workflows.

Note

High Risk
Changes touch permission evaluation, warehouse SQL execution paths (EXPLAIN ANALYZE and write classification), and a new agent that can propose edits and approved shell/dbt builds—mistakes could allow unintended writes or bypass user denials.

Overview
Introduces the dbt-optimizer primary agent: a deny-by-default allowlist for scan/analysis/finops tools, approval-gated edit/bash, and a non-overridable sql_execute_write deny (re-applied after global and per-agent config merges). A new prompt defines a four-phase loop (scan → fix → impact → PR) across six optimization lanes with cost-honesty rules; docs and builder self-review now nudge users to switch agents instead of silent out-of-scope fixes.

SQL and verification behavior is tightened: a lexer-based maskLiteralsAndComments backs safer write classification (side-effect functions, read-shaped writes) and sql_explain blocks or permission-gates analyze:true so executing plans cannot bypass warehouse-write controls. sql_diff / equivalence tooling now match the native handler (LCS diffs, equivalence_assessed / decidable) and treat undecidable results as unproven across rewrite/equivalence surfaces.

Path and session safety: dbt manifest/lineage/parse tools and schema_path arguments go through external_directory gating with project-relative resolution; schema_index and training mutations prompt explicitly. Permission evaluation no longer lets stored “always allow” approvals override configured deny rules (protecting optimizer/reviewer write denials after agent switches). impact_analysis downstream traversal is improved (multi-seed BFS by unique_id, clearer column-impact caveats).

Reviewed by Cursor Bugbot for commit 81ec904. Bugbot is set up for automated code reviews on this repo. Configure here.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a dbt-optimizer agent: scan dbt projects for fixable issues with cost/impact reporting

1 participant