{"owner":"dbt-labs","repo":"dbt-core","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":4803,"categories":["root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".agents/skills/adapters-annotate-references/SKILL.md",".agents/skills/adapters-critic/SKILL.md"],"skills":{"AGENTS.md":"# Project Instructions (AI Agents)\n\nThese instructions are for coding agents (Codex CLI, Claude Code, etc).\n\nPaths in this file and in `.agents/` are relative to the directory containing this file.\n\n## Hard Rules\n\n### Code Style\n\n- Follow existing code style and patterns in the given crate/module.\n- Keep changes minimal and focused to the task at hand.\n- Prefer simple, readable code over clever or complex solutions.\n\n### Changelog\n\n- Never manually create or write changelog YAML files. Always use `changie new` to generate entries.\n- Run `changie new` from the repository root with flags: `changie new --kind \"<kind>\" --body \"<description>\" --custom \"project=<project>\" --custom \"issue=<number>\" --custom \"author=<handle>\" --interactive=false`\n- For optional empty fields (`issue`, `author`), prompt the user if running locally or pass a space (e.g., `--custom \"issue= \"`) then edit the generated file to replace `' '` with `\"\"`.\n\n### Logging and printing\n\n- Never call `tracing::{error,warn,info,debug,trace}!` or `tracing::event!`, and never use `println!`/`eprintln!`/`print!`/`eprint!`. This includes debug-only and internal code.\n- Emit a structured event if one exists (`LogMessage`, `ProgressMessage`, ...). Otherwise use the level helper in `dbt_common::tracing::dbt_emit`: `emit_error_log_message`, `emit_warn_log_message`, `emit_info_log_message`, `emit_debug_log_message`, `emit_trace_log_message`.\n- Only for output strictly to the CLI with no trace: `dbt_emit::print_err` instead of `eprintln!`, `dbt_emit::print`/`println` instead of `print!`/`println!`.\n- Why: the emit helpers use `#[track_caller]` to record the call site and pass telemetry attributes through thread-local storage, and their events are exported to OTEL. The macros bypass both.\n- Create spans with `create_info_span`/`create_debug_span` (`dbt_tracing::emit`), not `tracing::span!`. `#[tracing::instrument]`, `tracing::Instrument` and `Span::current()` are fine.\n- Exceptions to the print ban: `build.rs` (`println!(\"cargo:...\")` directives), tests, and `xtask`/dev tooling (`crates/xtask`, `dbt-ci`, `examples/`, `benches/`).\n- Details: `.agents/telemetry-tracing.md`.\n\n### Error codes\n\n- Never use `ErrorCode::Generic` in new code. It carries no signal about what went wrong.\n- Use `ErrorCode::Unexpected` only for a true internal inconsistent state, meaning an invariant the code itself broke. Never use it for errors caused by user input, config, project files, or the warehouse.\n- Otherwise use the most specific existing `ErrorCode`, or add a new one in `crates/dbt-error/src/codes.rs` (CLI codes `[1000, 8999]`, internal `[9000, 9899]`; frontend codes come from `dbt_frontend_common::error::ErrorCode`, don't add them here).\n- Why: codes `>= 9000` are reported as Fusion bugs (`ErrorCode::is_bug`), so misusing `Unexpected` inflates bug counts and hides the real cause. User-facing codes (`dbtNNNN`) tell users what to fix, and `warn_error_options` targets codes, so a shared code makes users promote or silence unrelated warnings. Give each new warning its own code.\n- Existing `Generic`/`Unexpected` sites are legacy; don't copy them.\n\n### Running dev commands\n\n- Never run blanket `cargo` commands without `-p <crate>` unless explicitly asked.\n- Avoid context pollution: don’t paste long logs; prefer LLM-friendly JSONL output and short excerpts.\n- Avoid full builds and full test runs during iteration; keep commands scoped and fast.\n\n## Where To Look Next (Task-Specific)\n\n- Respect author preferences (optional/local): `AGENTS.local.md`\n- When writing, running or recording adapter record/replay tests (end-to-end tests against a warehouse): `crates/dbt-sa-adapter-tests/README.md`\n- When working on Adapters: `.agents/adapters.md`. Adapters consist of the following crates:\n  - `dbt-adapter`\n  - `dbt-adapter-core`\n  - `dbt-adapter-sql`\n  - `dbt-auth`\n  - `dbt-sql-keywords`\n  - `dbt-adbc`\n- When working on telemetry/tracing: `.agents/telemetry-tracing.md`\n- When working on dbt-docs-server (static site + DuckDB-WASM in the browser): `.agents/dbt-docs-server.md`\n- When adding, graduating, or removing a feature flag or behavior flag, or reading one at a call site: declare it in `crates/dbt-flags/src/catalog.rs`; precedence and stages are documented in `crates/dbt-flags/src/lib.rs`. Do not add new `std::env::var` toggles or `project_flags_get_value` lookups for this.\n- Always check for nested `AGENTS.md` files in subdirectories you modify\n- If context is not enough, try reading repo overview / architecture as last resort: `README.md`\n",".agents/skills/adapters-annotate-references/SKILL.md":"---\nname: adapter-skills-annotate-references\ndescription: Use when annotating fs adapter implementations with upstream dbt-adapters Python reference links. Triggers whenever you need to add or audit GitHub permalink comments in adapter_impl.rs, trace an fs adapter method back to its Python origin in dbt-adapters, or when working on adapter divergence and want to know where a method came from. Also use when asked to \"annotate references\", \"add upstream links\", or \"link adapter methods\".\n---\n\n# Adapter Skills: Annotate References\n\nWalks the Python `@available` method chain (`BaseAdapter → SQLAdapter → [Platform]Adapter`) and\nannotates the corresponding Rust `pub fn` methods in `adapter_impl.rs` with permanent upstream\nGitHub links. Methods present in Python but absent in Rust are written to a gap report.\n\n## Background\n\n`fs` implements adapter methods in Rust, drawing from the Python inheritance chain:\n\n```\nBaseAdapter  (dbt-adapters/src/dbt/adapters/base/impl.py)\n  └── SQLAdapter  (dbt-adapters/src/dbt/adapters/sql/impl.py)\n        └── PlatformAdapter  (dbt-{bigquery,snowflake,redshift,spark}/src/dbt/adapters/{platform}/impl.py)\n```\n\nThe dbt-adapters repo is a **monorepo** (Snowflake, BigQuery, Redshift, Spark, Postgres, Athena,\nplus the base and SQL layers). Databricks lives in a **separate** repo.\n\n`@available` (and variants `@available.parse_list`, `@available.parse_none`, `@available.parse(…)`)\nmarks methods exposed to the Jinja environment. Starting from Python guarantees full coverage,\nincluding platform-specific methods that only exist in one adapter's `impl.py`.\n\n---\n\n## Step 0 — Gather configuration\n\nAsk the user two questions:\n\n1. **Local path to the dbt-adapters checkout** (the dbt-labs monorepo):\n   > What is the local path to your dbt-adapters checkout? (e.g. `~/code/dbt-adapters`)\n\n2. **Any other adapter repos to include?** (comma-separated, optional):\n   > e.g. `~/code/dbt-databricks` — leave blank if none\n\nThe gap report defaults to `missing_adapter_methods.md` at the repo root.\n\n---\n\n## Step 1 — Run the reverse annotation script\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/annotate.py \\\n    --adapter-impl <path/to/adapter_impl.rs> \\\n    --dbt-adapters <dbt-adapters-path> \\\n    --all-adapters \\\n    [--extra-repos <path1>,<path2>,...] \\\n    [--missing-out missing_adapter_methods.md] \\\n    [--dry-run]\n```\n\nAlways pass `--all-adapters` to scan the full monorepo. Use `--extra-repos` for repos outside\nit (e.g. dbt-databricks). Use `--dry-run` to preview without writing.\n\nThe script:\n1. Enumerates all `@available` methods across every `*impl.py` in the provided repos.\n2. Scans `adapter_impl.rs` for `pub fn` methods.\n3. For methods **found in Rust, not yet annotated** → inserts `/// ClassName <url>`.\n4. For methods **not found in Rust** → records them in the gap report.\n5. Prints a JSON summary to stdout: `{annotated, already_annotated, missing_from_rust, …}`.\n\n---\n\n## Step 2 — Review the results\n\n**Annotations:** spot-check a few inserted lines:\n```rust\n/// BigQueryAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-bigquery/src/dbt/adapters/bigquery/impl.py#L42\npub fn load_dataframes(\n```\n\n**Gap report** (`missing_adapter_methods.md`): rendered in canonical adapter order — Snowflake,\nBigQuery, Redshift, Spark, Postgres, Athena, then any extra repos (e.g. Databricks), then\nBase / SQL Adapter. Adapters with full coverage show ✅. Share the report with the user and\ndecide whether any missing methods need follow-up porting work.\n\n---\n\n## Annotation format\n\n```\n/// <ClassName> <github-permalink>\n```\n\n**Placement** (handled automatically):\n- No existing `///` block → insert above the first `#[…]` attribute (or above `pub fn` directly).\n- Existing `///` block → append after its last line, with a blank `///` separator if needed.\n\n```rust\n// No prior doc comment:\n/// BaseAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-adapters/src/dbt/adapters/base/impl.py#L862\n#[tracing::instrument(…)]\npub fn get_missing_columns(\n\n// Existing doc comment:\n/// Returns columns present in source but absent in target.\n///\n/// BaseAdapter https://…/base/impl.py#L862\npub fn get_missing_columns(\n```\n\nThe class name prefix (`BaseAdapter`, `SQLAdapter`, `SnowflakeAdapter`, …) tells readers at a\nglance which level of the hierarchy the method comes from.\n\n---\n\n## Step 3 — Verify\n\n```bash\ncargo check -p dbt-adapter\ncargo nextest run -p dbt-adapter\n```\n\n---\n\n## Per-method lookup\n\nTo investigate a single method's upstream origin:\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/find_upstream.py \\\n    <method_name> <dbt-adapters-path> \\\n    [--adapter-type <type>] \\\n    [--extra-repos <path>]\n```\n\nReturns JSON with `found`, `best` (lowest-priority = most specific match), `all_matches`, and\n`non_available_matches`. Only `@available`-decorated methods appear in `all_matches`; the rest\nare in `non_available_matches` for debugging. When `found: false`, skip — no annotation needed.\n\n---\n\n## Notes\n\n- `///` doc comment → method-level upstream link (what this skill adds)\n- `//` inline comment → within-body line notes (leave as-is)\n- Scripts use the current git SHA for stable permalinks; never use `main`-based URLs.\n- Monorepo package URLs are repo-root-relative: `dbt-bigquery/src/…`, `dbt-adapters/src/…`\n",".agents/skills/adapters-critic/SKILL.md":"---\nname: adapters-critic\ndescription: Use in a reviewer agent in agent loops or when reviewing your own code.\nwhen_to_use: Use before editing any code in Adapters or related crates.\nargument: [tentative-edit]\ncontext: fork\nallowed-tools: Bash(git log *) Bash(git diff *) Bash(grep) Bash(ls) Bash(cat)\n---\n\n# Your task\n\nYou are a code critic agent: your job is to find flaws in code written by other agents or humans, according to the project's intended architecture principles.\n\nStep by step review process follows.\n\n## Load the patch\n\nIf the patch body:\n- Is empty, use `git diff HEAD` instead\n- Is a path to a file, read that file and use the contents instead\n- Is a verbatim git patch, use it as-is\n\n## Identify which adapter is being worked on\n\nUsually, a patch relates to a specific `AdapterType`, like `DuckDB`, `Bigquery` or `Snowflake`.\n\nIdentify which one we're talking about. From now on, we'll refer to that as `FoofingAdapter` (or `foofing`).\n\n\n## Code review\n\nYou will perform a few sub-steps, each looking for a specific pattern or code smell that is considered bad according to the architecture goals. You will generate a comment with a succint description and suggest an edit if you find that that code is bad.\n\nThese are the substeps:\n\n### Code review - step 1: Find duplicated code\n\nLook for code that is a plain copy of other code, for example\n```\nfn my_function() {\n    // ...\n    if adapter_type == AdapterType::FoofingAdapter {\n        // duplicate code, just added a wrapper call\n        return a(b(c));\n    }\n    b(c)\n}\n```\n\nSuggest compressing the code so that it works generically across platforms. In the example above, you'd suggest sharing as most of the code paths as possible, by sharing the call to `b(c)` and not just copying it\n```\nfn my_function() {\n    // ...\n    let result = b(c);\n    let result = match adapter_type {\n        AdapterType::FoofingAdapter => a(result),\n        _ => {},\n    }\n    result\n}\n```\n\nAnother example of bad code:\n```\nlet relation = match adapter_type {\n    AdapterType::FoofingAdapter => Relation::new(adapter_type)\n            .with_quoting(Policy::trues()),\n    AdapterType::Another => Relation::new(adapter_type)\n            .with_quoting(Policy::falses()),\n}\n```\n\nReplace with a single callsite to `new()` and `with_quoting()`\n```\nlet quoting = match adapter_type {\n    AdapterType::FoofingAdapter => Policy::trues(),\n    AdapterType::Another => Policy::falses(),\n};\nlet relation = Relation::new(adapter_type).with_quoting(quoting);\n```\n\n### Code review - step 2: Avoid target-specific free functions\n\nLook for platform-specific free functions, structs or enums outside of platform-specific modules, this is a red flag. Code such as the following should be avoided in generic modules:\n```\nenum ClickhouseSomething {\n   // ...\n}\n\nstruct FabricSomethingElse {\n   // ...\n}\n\nfn foofing_do_something() {\n}\n\nfn duckdb_foo_bar() {\n}\n\nfn lala_bigquery_lele() {\n}\n\nfn do_something_in_snowflake() {\n}\n```\n\nIn generic modules such as `relation_impl.rs`, `adapter_impl.rs` and `dbt-adbc`, there should be only generic code with `match adapter_type` statements that call entrypoints to the platform-specific modules.\n\nSuggest replacing with something along the lines of:\n\n```\n// In the `foofing` module\nfn foofing_do_something() {\n    // platform-specific code goes here\n}\n\n// In the generic module\nuse crate::submodule::foofing::foofing_do_something()\n\nfn do_something() {\n    match adapter_type {\n        AdapterType::FoofingAdapter => foofing_do_something(),\n        AdapterType::Bigquery => panic!(\"Bigquery does not support do_something()\")\n        _ => unimplemented!(\"do_something() unimplemented for this adapter_type\")\n    }\n}\n```\n\nNote that it is OK to do `panic!()` in other code if the other platform does not implement that feature, or `unimplemented!()` if we haven't done it for that platform yet.\n\n**Real example:** `adapter/mod.rs` used to register two Jinja-dispatched entrypoints, each hardcoded to one Snowflake relation type, sitting right next to `describe_relation` — a generic, adapter-agnostic name already used by BigQuery:\n\n```rust\n\"describe_dynamic_table\" => self.describe_dynamic_table(state, args),\n\"describe_interactive_table\" => self.describe_interactive_table(state, args),\n```\n\nFixed (PR #13201, following up on #12664 review feedback) by keeping one Jinja-facing name and dispatching internally on adapter type and relation type, instead of on the Jinja method name:\n\n```rust\nif adapter.adapter_type() == AdapterType::Snowflake {\n    match relation.relation_type() {\n        Some(RelationType::DynamicTable) => adapter.describe_dynamic_table(/* ... */),\n        Some(RelationType::InteractiveTable) => adapter.describe_interactive_table(/* ... */),\n        other => Err(minijinja::Error::new(\n            minijinja::ErrorKind::InvalidOperation,\n            format!(\"describe_relation is not supported for relation type {other:?} on Snowflake\"),\n        )),\n    }\n} else {\n    Ok(adapter.describe_relation(conn.as_mut(), &relation, Some(state))?\n        .map(Value::from_object)\n        .unwrap_or_else(none_value))\n}\n```\n\nThe old per-type Rust methods stayed as private helpers called from the match arms — only the Jinja-facing dispatch surface needed to become generic, not the method bodies themselves.\n\n### Code review - step 3: No SQL-processing utilities outside of `dbt-adapter-sql` or `dbt-adapter-keywords`\n\nIf you find SQL keyword normalization/sanitization, statement splitting, keyword detection etc outside of the `dbt-adapter-sql` and `dbt-adapter-keywords` crates, suggest moving those there. You may explore those crates to give better suggestions of how to port the code. Example code that should live in these crates.\n\n```\nfn format_identifier() {\n    // do SQL identifier formatting\n}\n\nfn sanitize_identifier() {\n    // do SQL identifier sanitization\n}\n\nfn requires_quotes() {\n    // check if an identifier requires quotes\n}\n```\n\nIf those are free functions, apply the same rules as in \"step 2\" and suggest a generic function that does `match adapter_type`. You can look at the existing functions in `dbt-adapter-sql` and `dbt-adapter-keywords` to see if code can be consolidated.\n\n\n### Code review - step 4: Replace `if adapter_type` with `match`\n\nWhat to look for:\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n    return;\n}\n// generic code\n```\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n} else {\n    // generic code\n}\n```\n\nSuggest replacing with:\n\n```\nmatch adapter_type {\n    AdapterType::FoofingAdapter => {\n        // target-specific code\n    }\n    _ => {\n        // generic code\n    }\n}\n```\n\n### Code review - step 5: No useless comments\n\nFind obvious comments that directly comment what the following code does, for example\n```\nlet db = match adapter_type {\n    // THE COMMENT BELOW IS BAD\n    // database is uppercased in Foofing\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nInstead, suggest simply deleting the the comment:\n```\nlet db = match adapter_type {\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nThe one exception is if the comment carries meaningful information that is not expressed in the code. In such cases, the code should ALWAYS be annotated with reference links to more context.\n\nFor example, the following comment is okay:\n```\nlet db = match adapter_type {\n    // For historical reasons, Foofing does database uppercasing to avoid identifier conflicts when foo bars.\n    // Original Python adapter implementation: <link to python code>\n    // Documentation for Foofing identifier matching: <link to python code>\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\n### Code review - step 6: Final questions\n\nAsk yourself: \n- Does this function/struct/enum belong here? Is there any other code in the codebase that does the same/similar thing? Where does that code live? Consider whether that might be a more appropriate module for that code.\n- Are there any free functions returning booleans that drive one-off control flow? That is bad.\n\n## Output\n\nAfter gathering all the steps above, you will output your findings in markdown consisting of \"header with short explanation, file:lineno, patch\". DO NOT output your reasoning or long prose, only the necessary patch, file name/line number and a SHORT, succint description. \n\nFor example, the output should look like:\n\n<example>\n# replace `if adapter_type` with match\n\nBEFORE: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nif adapter_type == AdapterType::Foofing {\n  the_code()\n} else {\n  other_code()\n}\n```\n\nAFTER: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nmatch adapter_type {\n  AdapterType::Foofing => the_code(),\n  _ => other_code(),\n}\n```\n\n# move `foofing_do_something()` to `my_module::foofing()`\n\nBEFORE: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nfn foofing_do_something() {\n    // the code\n}\n```\n\nAFTER: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nuse my_module::foofing;\n\nfn do_something(adapter_type: AdapterType) {\n    match adapter_type {\n        AdapterType::Foofing => foofing::do_something(),\n        _ => unimplemented!(),\n    }\n}\n```\n\nAFTER: `crates/my-crate/src/my_module.rs`\n```\nfn do_something() {\n    // the code\n}\n```\n</example>\n\n\n# Time to execute\n\nInstructions done. Go execute.\n\nThe patch body is:\n\n```\n$ARGUMENTS[0]\n```\n"},"files":{"AGENTS.md":"# Project Instructions (AI Agents)\n\nThese instructions are for coding agents (Codex CLI, Claude Code, etc).\n\nPaths in this file and in `.agents/` are relative to the directory containing this file.\n\n## Hard Rules\n\n### Code Style\n\n- Follow existing code style and patterns in the given crate/module.\n- Keep changes minimal and focused to the task at hand.\n- Prefer simple, readable code over clever or complex solutions.\n\n### Changelog\n\n- Never manually create or write changelog YAML files. Always use `changie new` to generate entries.\n- Run `changie new` from the repository root with flags: `changie new --kind \"<kind>\" --body \"<description>\" --custom \"project=<project>\" --custom \"issue=<number>\" --custom \"author=<handle>\" --interactive=false`\n- For optional empty fields (`issue`, `author`), prompt the user if running locally or pass a space (e.g., `--custom \"issue= \"`) then edit the generated file to replace `' '` with `\"\"`.\n\n### Logging and printing\n\n- Never call `tracing::{error,warn,info,debug,trace}!` or `tracing::event!`, and never use `println!`/`eprintln!`/`print!`/`eprint!`. This includes debug-only and internal code.\n- Emit a structured event if one exists (`LogMessage`, `ProgressMessage`, ...). Otherwise use the level helper in `dbt_common::tracing::dbt_emit`: `emit_error_log_message`, `emit_warn_log_message`, `emit_info_log_message`, `emit_debug_log_message`, `emit_trace_log_message`.\n- Only for output strictly to the CLI with no trace: `dbt_emit::print_err` instead of `eprintln!`, `dbt_emit::print`/`println` instead of `print!`/`println!`.\n- Why: the emit helpers use `#[track_caller]` to record the call site and pass telemetry attributes through thread-local storage, and their events are exported to OTEL. The macros bypass both.\n- Create spans with `create_info_span`/`create_debug_span` (`dbt_tracing::emit`), not `tracing::span!`. `#[tracing::instrument]`, `tracing::Instrument` and `Span::current()` are fine.\n- Exceptions to the print ban: `build.rs` (`println!(\"cargo:...\")` directives), tests, and `xtask`/dev tooling (`crates/xtask`, `dbt-ci`, `examples/`, `benches/`).\n- Details: `.agents/telemetry-tracing.md`.\n\n### Error codes\n\n- Never use `ErrorCode::Generic` in new code. It carries no signal about what went wrong.\n- Use `ErrorCode::Unexpected` only for a true internal inconsistent state, meaning an invariant the code itself broke. Never use it for errors caused by user input, config, project files, or the warehouse.\n- Otherwise use the most specific existing `ErrorCode`, or add a new one in `crates/dbt-error/src/codes.rs` (CLI codes `[1000, 8999]`, internal `[9000, 9899]`; frontend codes come from `dbt_frontend_common::error::ErrorCode`, don't add them here).\n- Why: codes `>= 9000` are reported as Fusion bugs (`ErrorCode::is_bug`), so misusing `Unexpected` inflates bug counts and hides the real cause. User-facing codes (`dbtNNNN`) tell users what to fix, and `warn_error_options` targets codes, so a shared code makes users promote or silence unrelated warnings. Give each new warning its own code.\n- Existing `Generic`/`Unexpected` sites are legacy; don't copy them.\n\n### Running dev commands\n\n- Never run blanket `cargo` commands without `-p <crate>` unless explicitly asked.\n- Avoid context pollution: don’t paste long logs; prefer LLM-friendly JSONL output and short excerpts.\n- Avoid full builds and full test runs during iteration; keep commands scoped and fast.\n\n## Where To Look Next (Task-Specific)\n\n- Respect author preferences (optional/local): `AGENTS.local.md`\n- When writing, running or recording adapter record/replay tests (end-to-end tests against a warehouse): `crates/dbt-sa-adapter-tests/README.md`\n- When working on Adapters: `.agents/adapters.md`. Adapters consist of the following crates:\n  - `dbt-adapter`\n  - `dbt-adapter-core`\n  - `dbt-adapter-sql`\n  - `dbt-auth`\n  - `dbt-sql-keywords`\n  - `dbt-adbc`\n- When working on telemetry/tracing: `.agents/telemetry-tracing.md`\n- When working on dbt-docs-server (static site + DuckDB-WASM in the browser): `.agents/dbt-docs-server.md`\n- When adding, graduating, or removing a feature flag or behavior flag, or reading one at a call site: declare it in `crates/dbt-flags/src/catalog.rs`; precedence and stages are documented in `crates/dbt-flags/src/lib.rs`. Do not add new `std::env::var` toggles or `project_flags_get_value` lookups for this.\n- Always check for nested `AGENTS.md` files in subdirectories you modify\n- If context is not enough, try reading repo overview / architecture as last resort: `README.md`\n",".agents/skills/adapters-annotate-references/SKILL.md":"---\nname: adapter-skills-annotate-references\ndescription: Use when annotating fs adapter implementations with upstream dbt-adapters Python reference links. Triggers whenever you need to add or audit GitHub permalink comments in adapter_impl.rs, trace an fs adapter method back to its Python origin in dbt-adapters, or when working on adapter divergence and want to know where a method came from. Also use when asked to \"annotate references\", \"add upstream links\", or \"link adapter methods\".\n---\n\n# Adapter Skills: Annotate References\n\nWalks the Python `@available` method chain (`BaseAdapter → SQLAdapter → [Platform]Adapter`) and\nannotates the corresponding Rust `pub fn` methods in `adapter_impl.rs` with permanent upstream\nGitHub links. Methods present in Python but absent in Rust are written to a gap report.\n\n## Background\n\n`fs` implements adapter methods in Rust, drawing from the Python inheritance chain:\n\n```\nBaseAdapter  (dbt-adapters/src/dbt/adapters/base/impl.py)\n  └── SQLAdapter  (dbt-adapters/src/dbt/adapters/sql/impl.py)\n        └── PlatformAdapter  (dbt-{bigquery,snowflake,redshift,spark}/src/dbt/adapters/{platform}/impl.py)\n```\n\nThe dbt-adapters repo is a **monorepo** (Snowflake, BigQuery, Redshift, Spark, Postgres, Athena,\nplus the base and SQL layers). Databricks lives in a **separate** repo.\n\n`@available` (and variants `@available.parse_list`, `@available.parse_none`, `@available.parse(…)`)\nmarks methods exposed to the Jinja environment. Starting from Python guarantees full coverage,\nincluding platform-specific methods that only exist in one adapter's `impl.py`.\n\n---\n\n## Step 0 — Gather configuration\n\nAsk the user two questions:\n\n1. **Local path to the dbt-adapters checkout** (the dbt-labs monorepo):\n   > What is the local path to your dbt-adapters checkout? (e.g. `~/code/dbt-adapters`)\n\n2. **Any other adapter repos to include?** (comma-separated, optional):\n   > e.g. `~/code/dbt-databricks` — leave blank if none\n\nThe gap report defaults to `missing_adapter_methods.md` at the repo root.\n\n---\n\n## Step 1 — Run the reverse annotation script\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/annotate.py \\\n    --adapter-impl <path/to/adapter_impl.rs> \\\n    --dbt-adapters <dbt-adapters-path> \\\n    --all-adapters \\\n    [--extra-repos <path1>,<path2>,...] \\\n    [--missing-out missing_adapter_methods.md] \\\n    [--dry-run]\n```\n\nAlways pass `--all-adapters` to scan the full monorepo. Use `--extra-repos` for repos outside\nit (e.g. dbt-databricks). Use `--dry-run` to preview without writing.\n\nThe script:\n1. Enumerates all `@available` methods across every `*impl.py` in the provided repos.\n2. Scans `adapter_impl.rs` for `pub fn` methods.\n3. For methods **found in Rust, not yet annotated** → inserts `/// ClassName <url>`.\n4. For methods **not found in Rust** → records them in the gap report.\n5. Prints a JSON summary to stdout: `{annotated, already_annotated, missing_from_rust, …}`.\n\n---\n\n## Step 2 — Review the results\n\n**Annotations:** spot-check a few inserted lines:\n```rust\n/// BigQueryAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-bigquery/src/dbt/adapters/bigquery/impl.py#L42\npub fn load_dataframes(\n```\n\n**Gap report** (`missing_adapter_methods.md`): rendered in canonical adapter order — Snowflake,\nBigQuery, Redshift, Spark, Postgres, Athena, then any extra repos (e.g. Databricks), then\nBase / SQL Adapter. Adapters with full coverage show ✅. Share the report with the user and\ndecide whether any missing methods need follow-up porting work.\n\n---\n\n## Annotation format\n\n```\n/// <ClassName> <github-permalink>\n```\n\n**Placement** (handled automatically):\n- No existing `///` block → insert above the first `#[…]` attribute (or above `pub fn` directly).\n- Existing `///` block → append after its last line, with a blank `///` separator if needed.\n\n```rust\n// No prior doc comment:\n/// BaseAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-adapters/src/dbt/adapters/base/impl.py#L862\n#[tracing::instrument(…)]\npub fn get_missing_columns(\n\n// Existing doc comment:\n/// Returns columns present in source but absent in target.\n///\n/// BaseAdapter https://…/base/impl.py#L862\npub fn get_missing_columns(\n```\n\nThe class name prefix (`BaseAdapter`, `SQLAdapter`, `SnowflakeAdapter`, …) tells readers at a\nglance which level of the hierarchy the method comes from.\n\n---\n\n## Step 3 — Verify\n\n```bash\ncargo check -p dbt-adapter\ncargo nextest run -p dbt-adapter\n```\n\n---\n\n## Per-method lookup\n\nTo investigate a single method's upstream origin:\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/find_upstream.py \\\n    <method_name> <dbt-adapters-path> \\\n    [--adapter-type <type>] \\\n    [--extra-repos <path>]\n```\n\nReturns JSON with `found`, `best` (lowest-priority = most specific match), `all_matches`, and\n`non_available_matches`. Only `@available`-decorated methods appear in `all_matches`; the rest\nare in `non_available_matches` for debugging. When `found: false`, skip — no annotation needed.\n\n---\n\n## Notes\n\n- `///` doc comment → method-level upstream link (what this skill adds)\n- `//` inline comment → within-body line notes (leave as-is)\n- Scripts use the current git SHA for stable permalinks; never use `main`-based URLs.\n- Monorepo package URLs are repo-root-relative: `dbt-bigquery/src/…`, `dbt-adapters/src/…`\n",".agents/skills/adapters-critic/SKILL.md":"---\nname: adapters-critic\ndescription: Use in a reviewer agent in agent loops or when reviewing your own code.\nwhen_to_use: Use before editing any code in Adapters or related crates.\nargument: [tentative-edit]\ncontext: fork\nallowed-tools: Bash(git log *) Bash(git diff *) Bash(grep) Bash(ls) Bash(cat)\n---\n\n# Your task\n\nYou are a code critic agent: your job is to find flaws in code written by other agents or humans, according to the project's intended architecture principles.\n\nStep by step review process follows.\n\n## Load the patch\n\nIf the patch body:\n- Is empty, use `git diff HEAD` instead\n- Is a path to a file, read that file and use the contents instead\n- Is a verbatim git patch, use it as-is\n\n## Identify which adapter is being worked on\n\nUsually, a patch relates to a specific `AdapterType`, like `DuckDB`, `Bigquery` or `Snowflake`.\n\nIdentify which one we're talking about. From now on, we'll refer to that as `FoofingAdapter` (or `foofing`).\n\n\n## Code review\n\nYou will perform a few sub-steps, each looking for a specific pattern or code smell that is considered bad according to the architecture goals. You will generate a comment with a succint description and suggest an edit if you find that that code is bad.\n\nThese are the substeps:\n\n### Code review - step 1: Find duplicated code\n\nLook for code that is a plain copy of other code, for example\n```\nfn my_function() {\n    // ...\n    if adapter_type == AdapterType::FoofingAdapter {\n        // duplicate code, just added a wrapper call\n        return a(b(c));\n    }\n    b(c)\n}\n```\n\nSuggest compressing the code so that it works generically across platforms. In the example above, you'd suggest sharing as most of the code paths as possible, by sharing the call to `b(c)` and not just copying it\n```\nfn my_function() {\n    // ...\n    let result = b(c);\n    let result = match adapter_type {\n        AdapterType::FoofingAdapter => a(result),\n        _ => {},\n    }\n    result\n}\n```\n\nAnother example of bad code:\n```\nlet relation = match adapter_type {\n    AdapterType::FoofingAdapter => Relation::new(adapter_type)\n            .with_quoting(Policy::trues()),\n    AdapterType::Another => Relation::new(adapter_type)\n            .with_quoting(Policy::falses()),\n}\n```\n\nReplace with a single callsite to `new()` and `with_quoting()`\n```\nlet quoting = match adapter_type {\n    AdapterType::FoofingAdapter => Policy::trues(),\n    AdapterType::Another => Policy::falses(),\n};\nlet relation = Relation::new(adapter_type).with_quoting(quoting);\n```\n\n### Code review - step 2: Avoid target-specific free functions\n\nLook for platform-specific free functions, structs or enums outside of platform-specific modules, this is a red flag. Code such as the following should be avoided in generic modules:\n```\nenum ClickhouseSomething {\n   // ...\n}\n\nstruct FabricSomethingElse {\n   // ...\n}\n\nfn foofing_do_something() {\n}\n\nfn duckdb_foo_bar() {\n}\n\nfn lala_bigquery_lele() {\n}\n\nfn do_something_in_snowflake() {\n}\n```\n\nIn generic modules such as `relation_impl.rs`, `adapter_impl.rs` and `dbt-adbc`, there should be only generic code with `match adapter_type` statements that call entrypoints to the platform-specific modules.\n\nSuggest replacing with something along the lines of:\n\n```\n// In the `foofing` module\nfn foofing_do_something() {\n    // platform-specific code goes here\n}\n\n// In the generic module\nuse crate::submodule::foofing::foofing_do_something()\n\nfn do_something() {\n    match adapter_type {\n        AdapterType::FoofingAdapter => foofing_do_something(),\n        AdapterType::Bigquery => panic!(\"Bigquery does not support do_something()\")\n        _ => unimplemented!(\"do_something() unimplemented for this adapter_type\")\n    }\n}\n```\n\nNote that it is OK to do `panic!()` in other code if the other platform does not implement that feature, or `unimplemented!()` if we haven't done it for that platform yet.\n\n**Real example:** `adapter/mod.rs` used to register two Jinja-dispatched entrypoints, each hardcoded to one Snowflake relation type, sitting right next to `describe_relation` — a generic, adapter-agnostic name already used by BigQuery:\n\n```rust\n\"describe_dynamic_table\" => self.describe_dynamic_table(state, args),\n\"describe_interactive_table\" => self.describe_interactive_table(state, args),\n```\n\nFixed (PR #13201, following up on #12664 review feedback) by keeping one Jinja-facing name and dispatching internally on adapter type and relation type, instead of on the Jinja method name:\n\n```rust\nif adapter.adapter_type() == AdapterType::Snowflake {\n    match relation.relation_type() {\n        Some(RelationType::DynamicTable) => adapter.describe_dynamic_table(/* ... */),\n        Some(RelationType::InteractiveTable) => adapter.describe_interactive_table(/* ... */),\n        other => Err(minijinja::Error::new(\n            minijinja::ErrorKind::InvalidOperation,\n            format!(\"describe_relation is not supported for relation type {other:?} on Snowflake\"),\n        )),\n    }\n} else {\n    Ok(adapter.describe_relation(conn.as_mut(), &relation, Some(state))?\n        .map(Value::from_object)\n        .unwrap_or_else(none_value))\n}\n```\n\nThe old per-type Rust methods stayed as private helpers called from the match arms — only the Jinja-facing dispatch surface needed to become generic, not the method bodies themselves.\n\n### Code review - step 3: No SQL-processing utilities outside of `dbt-adapter-sql` or `dbt-adapter-keywords`\n\nIf you find SQL keyword normalization/sanitization, statement splitting, keyword detection etc outside of the `dbt-adapter-sql` and `dbt-adapter-keywords` crates, suggest moving those there. You may explore those crates to give better suggestions of how to port the code. Example code that should live in these crates.\n\n```\nfn format_identifier() {\n    // do SQL identifier formatting\n}\n\nfn sanitize_identifier() {\n    // do SQL identifier sanitization\n}\n\nfn requires_quotes() {\n    // check if an identifier requires quotes\n}\n```\n\nIf those are free functions, apply the same rules as in \"step 2\" and suggest a generic function that does `match adapter_type`. You can look at the existing functions in `dbt-adapter-sql` and `dbt-adapter-keywords` to see if code can be consolidated.\n\n\n### Code review - step 4: Replace `if adapter_type` with `match`\n\nWhat to look for:\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n    return;\n}\n// generic code\n```\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n} else {\n    // generic code\n}\n```\n\nSuggest replacing with:\n\n```\nmatch adapter_type {\n    AdapterType::FoofingAdapter => {\n        // target-specific code\n    }\n    _ => {\n        // generic code\n    }\n}\n```\n\n### Code review - step 5: No useless comments\n\nFind obvious comments that directly comment what the following code does, for example\n```\nlet db = match adapter_type {\n    // THE COMMENT BELOW IS BAD\n    // database is uppercased in Foofing\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nInstead, suggest simply deleting the the comment:\n```\nlet db = match adapter_type {\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nThe one exception is if the comment carries meaningful information that is not expressed in the code. In such cases, the code should ALWAYS be annotated with reference links to more context.\n\nFor example, the following comment is okay:\n```\nlet db = match adapter_type {\n    // For historical reasons, Foofing does database uppercasing to avoid identifier conflicts when foo bars.\n    // Original Python adapter implementation: <link to python code>\n    // Documentation for Foofing identifier matching: <link to python code>\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\n### Code review - step 6: Final questions\n\nAsk yourself: \n- Does this function/struct/enum belong here? Is there any other code in the codebase that does the same/similar thing? Where does that code live? Consider whether that might be a more appropriate module for that code.\n- Are there any free functions returning booleans that drive one-off control flow? That is bad.\n\n## Output\n\nAfter gathering all the steps above, you will output your findings in markdown consisting of \"header with short explanation, file:lineno, patch\". DO NOT output your reasoning or long prose, only the necessary patch, file name/line number and a SHORT, succint description. \n\nFor example, the output should look like:\n\n<example>\n# replace `if adapter_type` with match\n\nBEFORE: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nif adapter_type == AdapterType::Foofing {\n  the_code()\n} else {\n  other_code()\n}\n```\n\nAFTER: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nmatch adapter_type {\n  AdapterType::Foofing => the_code(),\n  _ => other_code(),\n}\n```\n\n# move `foofing_do_something()` to `my_module::foofing()`\n\nBEFORE: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nfn foofing_do_something() {\n    // the code\n}\n```\n\nAFTER: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nuse my_module::foofing;\n\nfn do_something(adapter_type: AdapterType) {\n    match adapter_type {\n        AdapterType::Foofing => foofing::do_something(),\n        _ => unimplemented!(),\n    }\n}\n```\n\nAFTER: `crates/my-crate/src/my_module.rs`\n```\nfn do_something() {\n    // the code\n}\n```\n</example>\n\n\n# Time to execute\n\nInstructions done. Go execute.\n\nThe patch body is:\n\n```\n$ARGUMENTS[0]\n```\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/dbt-labs/dbt-core/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Project Instructions (AI Agents)\n\nThese instructions are for coding agents (Codex CLI, Claude Code, etc).\n\nPaths in this file and in `.agents/` are relative to the directory containing this file.\n\n## Hard Rules\n\n### Code Style\n\n- Follow existing code style and patterns in the given crate/module.\n- Keep changes minimal and focused to the task at hand.\n- Prefer simple, readable code over clever or complex solutions.\n\n### Changelog\n\n- Never manually create or write changelog YAML files. Always use `changie new` to generate entries.\n- Run `changie new` from the repository root with flags: `changie new --kind \"<kind>\" --body \"<description>\" --custom \"project=<project>\" --custom \"issue=<number>\" --custom \"author=<handle>\" --interactive=false`\n- For optional empty fields (`issue`, `author`), prompt the user if running locally or pass a space (e.g., `--custom \"issue= \"`) then edit the generated file to replace `' '` with `\"\"`.\n\n### Logging and printing\n\n- Never call `tracing::{error,warn,info,debug,trace}!` or `tracing::event!`, and never use `println!`/`eprintln!`/`print!`/`eprint!`. This includes debug-only and internal code.\n- Emit a structured event if one exists (`LogMessage`, `ProgressMessage`, ...). Otherwise use the level helper in `dbt_common::tracing::dbt_emit`: `emit_error_log_message`, `emit_warn_log_message`, `emit_info_log_message`, `emit_debug_log_message`, `emit_trace_log_message`.\n- Only for output strictly to the CLI with no trace: `dbt_emit::print_err` instead of `eprintln!`, `dbt_emit::print`/`println` instead of `print!`/`println!`.\n- Why: the emit helpers use `#[track_caller]` to record the call site and pass telemetry attributes through thread-local storage, and their events are exported to OTEL. The macros bypass both.\n- Create spans with `create_info_span`/`create_debug_span` (`dbt_tracing::emit`), not `tracing::span!`. `#[tracing::instrument]`, `tracing::Instrument` and `Span::current()` are fine.\n- Exceptions to the print ban: `build.rs` (`println!(\"cargo:...\")` directives), tests, and `xtask`/dev tooling (`crates/xtask`, `dbt-ci`, `examples/`, `benches/`).\n- Details: `.agents/telemetry-tracing.md`.\n\n### Error codes\n\n- Never use `ErrorCode::Generic` in new code. It carries no signal about what went wrong.\n- Use `ErrorCode::Unexpected` only for a true internal inconsistent state, meaning an invariant the code itself broke. Never use it for errors caused by user input, config, project files, or the warehouse.\n- Otherwise use the most specific existing `ErrorCode`, or add a new one in `crates/dbt-error/src/codes.rs` (CLI codes `[1000, 8999]`, internal `[9000, 9899]`; frontend codes come from `dbt_frontend_common::error::ErrorCode`, don't add them here).\n- Why: codes `>= 9000` are reported as Fusion bugs (`ErrorCode::is_bug`), so misusing `Unexpected` inflates bug counts and hides the real cause. User-facing codes (`dbtNNNN`) tell users what to fix, and `warn_error_options` targets codes, so a shared code makes users promote or silence unrelated warnings. Give each new warning its own code.\n- Existing `Generic`/`Unexpected` sites are legacy; don't copy them.\n\n### Running dev commands\n\n- Never run blanket `cargo` commands without `-p <crate>` unless explicitly asked.\n- Avoid context pollution: don’t paste long logs; prefer LLM-friendly JSONL output and short excerpts.\n- Avoid full builds and full test runs during iteration; keep commands scoped and fast.\n\n## Where To Look Next (Task-Specific)\n\n- Respect author preferences (optional/local): `AGENTS.local.md`\n- When writing, running or recording adapter record/replay tests (end-to-end tests against a warehouse): `crates/dbt-sa-adapter-tests/README.md`\n- When working on Adapters: `.agents/adapters.md`. Adapters consist of the following crates:\n  - `dbt-adapter`\n  - `dbt-adapter-core`\n  - `dbt-adapter-sql`\n  - `dbt-auth`\n  - `dbt-sql-keywords`\n  - `dbt-adbc`\n- When working on telemetry/tracing: `.agents/telemetry-tracing.md`\n- When working on dbt-docs-server (static site + DuckDB-WASM in the browser): `.agents/dbt-docs-server.md`\n- When adding, graduating, or removing a feature flag or behavior flag, or reading one at a call site: declare it in `crates/dbt-flags/src/catalog.rs`; precedence and stages are documented in `crates/dbt-flags/src/lib.rs`. Do not add new `std::env::var` toggles or `project_flags_get_value` lookups for this.\n- Always check for nested `AGENTS.md` files in subdirectories you modify\n- If context is not enough, try reading repo overview / architecture as last resort: `README.md`\n","isInternal":false,"tokens":1149,"sizeBytes":4548},{"name":"SKILL.md","path":".agents/skills/adapters-annotate-references/SKILL.md","rawUrl":"https://raw.githubusercontent.com/dbt-labs/dbt-core/HEAD/.agents/skills/adapters-annotate-references/SKILL.md","title":"adapter-skills-annotate-references","category":"anthropic-skill","format":"markdown","content":"---\nname: adapter-skills-annotate-references\ndescription: Use when annotating fs adapter implementations with upstream dbt-adapters Python reference links. Triggers whenever you need to add or audit GitHub permalink comments in adapter_impl.rs, trace an fs adapter method back to its Python origin in dbt-adapters, or when working on adapter divergence and want to know where a method came from. Also use when asked to \"annotate references\", \"add upstream links\", or \"link adapter methods\".\n---\n\n# Adapter Skills: Annotate References\n\nWalks the Python `@available` method chain (`BaseAdapter → SQLAdapter → [Platform]Adapter`) and\nannotates the corresponding Rust `pub fn` methods in `adapter_impl.rs` with permanent upstream\nGitHub links. Methods present in Python but absent in Rust are written to a gap report.\n\n## Background\n\n`fs` implements adapter methods in Rust, drawing from the Python inheritance chain:\n\n```\nBaseAdapter  (dbt-adapters/src/dbt/adapters/base/impl.py)\n  └── SQLAdapter  (dbt-adapters/src/dbt/adapters/sql/impl.py)\n        └── PlatformAdapter  (dbt-{bigquery,snowflake,redshift,spark}/src/dbt/adapters/{platform}/impl.py)\n```\n\nThe dbt-adapters repo is a **monorepo** (Snowflake, BigQuery, Redshift, Spark, Postgres, Athena,\nplus the base and SQL layers). Databricks lives in a **separate** repo.\n\n`@available` (and variants `@available.parse_list`, `@available.parse_none`, `@available.parse(…)`)\nmarks methods exposed to the Jinja environment. Starting from Python guarantees full coverage,\nincluding platform-specific methods that only exist in one adapter's `impl.py`.\n\n---\n\n## Step 0 — Gather configuration\n\nAsk the user two questions:\n\n1. **Local path to the dbt-adapters checkout** (the dbt-labs monorepo):\n   > What is the local path to your dbt-adapters checkout? (e.g. `~/code/dbt-adapters`)\n\n2. **Any other adapter repos to include?** (comma-separated, optional):\n   > e.g. `~/code/dbt-databricks` — leave blank if none\n\nThe gap report defaults to `missing_adapter_methods.md` at the repo root.\n\n---\n\n## Step 1 — Run the reverse annotation script\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/annotate.py \\\n    --adapter-impl <path/to/adapter_impl.rs> \\\n    --dbt-adapters <dbt-adapters-path> \\\n    --all-adapters \\\n    [--extra-repos <path1>,<path2>,...] \\\n    [--missing-out missing_adapter_methods.md] \\\n    [--dry-run]\n```\n\nAlways pass `--all-adapters` to scan the full monorepo. Use `--extra-repos` for repos outside\nit (e.g. dbt-databricks). Use `--dry-run` to preview without writing.\n\nThe script:\n1. Enumerates all `@available` methods across every `*impl.py` in the provided repos.\n2. Scans `adapter_impl.rs` for `pub fn` methods.\n3. For methods **found in Rust, not yet annotated** → inserts `/// ClassName <url>`.\n4. For methods **not found in Rust** → records them in the gap report.\n5. Prints a JSON summary to stdout: `{annotated, already_annotated, missing_from_rust, …}`.\n\n---\n\n## Step 2 — Review the results\n\n**Annotations:** spot-check a few inserted lines:\n```rust\n/// BigQueryAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-bigquery/src/dbt/adapters/bigquery/impl.py#L42\npub fn load_dataframes(\n```\n\n**Gap report** (`missing_adapter_methods.md`): rendered in canonical adapter order — Snowflake,\nBigQuery, Redshift, Spark, Postgres, Athena, then any extra repos (e.g. Databricks), then\nBase / SQL Adapter. Adapters with full coverage show ✅. Share the report with the user and\ndecide whether any missing methods need follow-up porting work.\n\n---\n\n## Annotation format\n\n```\n/// <ClassName> <github-permalink>\n```\n\n**Placement** (handled automatically):\n- No existing `///` block → insert above the first `#[…]` attribute (or above `pub fn` directly).\n- Existing `///` block → append after its last line, with a blank `///` separator if needed.\n\n```rust\n// No prior doc comment:\n/// BaseAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-adapters/src/dbt/adapters/base/impl.py#L862\n#[tracing::instrument(…)]\npub fn get_missing_columns(\n\n// Existing doc comment:\n/// Returns columns present in source but absent in target.\n///\n/// BaseAdapter https://…/base/impl.py#L862\npub fn get_missing_columns(\n```\n\nThe class name prefix (`BaseAdapter`, `SQLAdapter`, `SnowflakeAdapter`, …) tells readers at a\nglance which level of the hierarchy the method comes from.\n\n---\n\n## Step 3 — Verify\n\n```bash\ncargo check -p dbt-adapter\ncargo nextest run -p dbt-adapter\n```\n\n---\n\n## Per-method lookup\n\nTo investigate a single method's upstream origin:\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/find_upstream.py \\\n    <method_name> <dbt-adapters-path> \\\n    [--adapter-type <type>] \\\n    [--extra-repos <path>]\n```\n\nReturns JSON with `found`, `best` (lowest-priority = most specific match), `all_matches`, and\n`non_available_matches`. Only `@available`-decorated methods appear in `all_matches`; the rest\nare in `non_available_matches` for debugging. When `found: false`, skip — no annotation needed.\n\n---\n\n## Notes\n\n- `///` doc comment → method-level upstream link (what this skill adds)\n- `//` inline comment → within-body line notes (leave as-is)\n- Scripts use the current git SHA for stable permalinks; never use `main`-based URLs.\n- Monorepo package URLs are repo-root-relative: `dbt-bigquery/src/…`, `dbt-adapters/src/…`\n","frontmatter":{"name":"adapter-skills-annotate-references","description":"Use when annotating fs adapter implementations with upstream dbt-adapters Python reference links. Triggers whenever you need to add or audit GitHub permalink comments in adapter_impl.rs, trace an fs adapter method back to its Python origin in dbt-adapters, or when working on adapter divergence and want to know where a method came from. Also use when asked to \"annotate references\", \"add upstream links\", or \"link adapter methods\"."},"isInternal":false,"tokens":1366,"sizeBytes":5395},{"name":"SKILL.md","path":".agents/skills/adapters-critic/SKILL.md","rawUrl":"https://raw.githubusercontent.com/dbt-labs/dbt-core/HEAD/.agents/skills/adapters-critic/SKILL.md","title":"adapters-critic","category":"anthropic-skill","format":"markdown","content":"---\nname: adapters-critic\ndescription: Use in a reviewer agent in agent loops or when reviewing your own code.\nwhen_to_use: Use before editing any code in Adapters or related crates.\nargument: [tentative-edit]\ncontext: fork\nallowed-tools: Bash(git log *) Bash(git diff *) Bash(grep) Bash(ls) Bash(cat)\n---\n\n# Your task\n\nYou are a code critic agent: your job is to find flaws in code written by other agents or humans, according to the project's intended architecture principles.\n\nStep by step review process follows.\n\n## Load the patch\n\nIf the patch body:\n- Is empty, use `git diff HEAD` instead\n- Is a path to a file, read that file and use the contents instead\n- Is a verbatim git patch, use it as-is\n\n## Identify which adapter is being worked on\n\nUsually, a patch relates to a specific `AdapterType`, like `DuckDB`, `Bigquery` or `Snowflake`.\n\nIdentify which one we're talking about. From now on, we'll refer to that as `FoofingAdapter` (or `foofing`).\n\n\n## Code review\n\nYou will perform a few sub-steps, each looking for a specific pattern or code smell that is considered bad according to the architecture goals. You will generate a comment with a succint description and suggest an edit if you find that that code is bad.\n\nThese are the substeps:\n\n### Code review - step 1: Find duplicated code\n\nLook for code that is a plain copy of other code, for example\n```\nfn my_function() {\n    // ...\n    if adapter_type == AdapterType::FoofingAdapter {\n        // duplicate code, just added a wrapper call\n        return a(b(c));\n    }\n    b(c)\n}\n```\n\nSuggest compressing the code so that it works generically across platforms. In the example above, you'd suggest sharing as most of the code paths as possible, by sharing the call to `b(c)` and not just copying it\n```\nfn my_function() {\n    // ...\n    let result = b(c);\n    let result = match adapter_type {\n        AdapterType::FoofingAdapter => a(result),\n        _ => {},\n    }\n    result\n}\n```\n\nAnother example of bad code:\n```\nlet relation = match adapter_type {\n    AdapterType::FoofingAdapter => Relation::new(adapter_type)\n            .with_quoting(Policy::trues()),\n    AdapterType::Another => Relation::new(adapter_type)\n            .with_quoting(Policy::falses()),\n}\n```\n\nReplace with a single callsite to `new()` and `with_quoting()`\n```\nlet quoting = match adapter_type {\n    AdapterType::FoofingAdapter => Policy::trues(),\n    AdapterType::Another => Policy::falses(),\n};\nlet relation = Relation::new(adapter_type).with_quoting(quoting);\n```\n\n### Code review - step 2: Avoid target-specific free functions\n\nLook for platform-specific free functions, structs or enums outside of platform-specific modules, this is a red flag. Code such as the following should be avoided in generic modules:\n```\nenum ClickhouseSomething {\n   // ...\n}\n\nstruct FabricSomethingElse {\n   // ...\n}\n\nfn foofing_do_something() {\n}\n\nfn duckdb_foo_bar() {\n}\n\nfn lala_bigquery_lele() {\n}\n\nfn do_something_in_snowflake() {\n}\n```\n\nIn generic modules such as `relation_impl.rs`, `adapter_impl.rs` and `dbt-adbc`, there should be only generic code with `match adapter_type` statements that call entrypoints to the platform-specific modules.\n\nSuggest replacing with something along the lines of:\n\n```\n// In the `foofing` module\nfn foofing_do_something() {\n    // platform-specific code goes here\n}\n\n// In the generic module\nuse crate::submodule::foofing::foofing_do_something()\n\nfn do_something() {\n    match adapter_type {\n        AdapterType::FoofingAdapter => foofing_do_something(),\n        AdapterType::Bigquery => panic!(\"Bigquery does not support do_something()\")\n        _ => unimplemented!(\"do_something() unimplemented for this adapter_type\")\n    }\n}\n```\n\nNote that it is OK to do `panic!()` in other code if the other platform does not implement that feature, or `unimplemented!()` if we haven't done it for that platform yet.\n\n**Real example:** `adapter/mod.rs` used to register two Jinja-dispatched entrypoints, each hardcoded to one Snowflake relation type, sitting right next to `describe_relation` — a generic, adapter-agnostic name already used by BigQuery:\n\n```rust\n\"describe_dynamic_table\" => self.describe_dynamic_table(state, args),\n\"describe_interactive_table\" => self.describe_interactive_table(state, args),\n```\n\nFixed (PR #13201, following up on #12664 review feedback) by keeping one Jinja-facing name and dispatching internally on adapter type and relation type, instead of on the Jinja method name:\n\n```rust\nif adapter.adapter_type() == AdapterType::Snowflake {\n    match relation.relation_type() {\n        Some(RelationType::DynamicTable) => adapter.describe_dynamic_table(/* ... */),\n        Some(RelationType::InteractiveTable) => adapter.describe_interactive_table(/* ... */),\n        other => Err(minijinja::Error::new(\n            minijinja::ErrorKind::InvalidOperation,\n            format!(\"describe_relation is not supported for relation type {other:?} on Snowflake\"),\n        )),\n    }\n} else {\n    Ok(adapter.describe_relation(conn.as_mut(), &relation, Some(state))?\n        .map(Value::from_object)\n        .unwrap_or_else(none_value))\n}\n```\n\nThe old per-type Rust methods stayed as private helpers called from the match arms — only the Jinja-facing dispatch surface needed to become generic, not the method bodies themselves.\n\n### Code review - step 3: No SQL-processing utilities outside of `dbt-adapter-sql` or `dbt-adapter-keywords`\n\nIf you find SQL keyword normalization/sanitization, statement splitting, keyword detection etc outside of the `dbt-adapter-sql` and `dbt-adapter-keywords` crates, suggest moving those there. You may explore those crates to give better suggestions of how to port the code. Example code that should live in these crates.\n\n```\nfn format_identifier() {\n    // do SQL identifier formatting\n}\n\nfn sanitize_identifier() {\n    // do SQL identifier sanitization\n}\n\nfn requires_quotes() {\n    // check if an identifier requires quotes\n}\n```\n\nIf those are free functions, apply the same rules as in \"step 2\" and suggest a generic function that does `match adapter_type`. You can look at the existing functions in `dbt-adapter-sql` and `dbt-adapter-keywords` to see if code can be consolidated.\n\n\n### Code review - step 4: Replace `if adapter_type` with `match`\n\nWhat to look for:\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n    return;\n}\n// generic code\n```\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n} else {\n    // generic code\n}\n```\n\nSuggest replacing with:\n\n```\nmatch adapter_type {\n    AdapterType::FoofingAdapter => {\n        // target-specific code\n    }\n    _ => {\n        // generic code\n    }\n}\n```\n\n### Code review - step 5: No useless comments\n\nFind obvious comments that directly comment what the following code does, for example\n```\nlet db = match adapter_type {\n    // THE COMMENT BELOW IS BAD\n    // database is uppercased in Foofing\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nInstead, suggest simply deleting the the comment:\n```\nlet db = match adapter_type {\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nThe one exception is if the comment carries meaningful information that is not expressed in the code. In such cases, the code should ALWAYS be annotated with reference links to more context.\n\nFor example, the following comment is okay:\n```\nlet db = match adapter_type {\n    // For historical reasons, Foofing does database uppercasing to avoid identifier conflicts when foo bars.\n    // Original Python adapter implementation: <link to python code>\n    // Documentation for Foofing identifier matching: <link to python code>\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\n### Code review - step 6: Final questions\n\nAsk yourself: \n- Does this function/struct/enum belong here? Is there any other code in the codebase that does the same/similar thing? Where does that code live? Consider whether that might be a more appropriate module for that code.\n- Are there any free functions returning booleans that drive one-off control flow? That is bad.\n\n## Output\n\nAfter gathering all the steps above, you will output your findings in markdown consisting of \"header with short explanation, file:lineno, patch\". DO NOT output your reasoning or long prose, only the necessary patch, file name/line number and a SHORT, succint description. \n\nFor example, the output should look like:\n\n<example>\n# replace `if adapter_type` with match\n\nBEFORE: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nif adapter_type == AdapterType::Foofing {\n  the_code()\n} else {\n  other_code()\n}\n```\n\nAFTER: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nmatch adapter_type {\n  AdapterType::Foofing => the_code(),\n  _ => other_code(),\n}\n```\n\n# move `foofing_do_something()` to `my_module::foofing()`\n\nBEFORE: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nfn foofing_do_something() {\n    // the code\n}\n```\n\nAFTER: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nuse my_module::foofing;\n\nfn do_something(adapter_type: AdapterType) {\n    match adapter_type {\n        AdapterType::Foofing => foofing::do_something(),\n        _ => unimplemented!(),\n    }\n}\n```\n\nAFTER: `crates/my-crate/src/my_module.rs`\n```\nfn do_something() {\n    // the code\n}\n```\n</example>\n\n\n# Time to execute\n\nInstructions done. Go execute.\n\nThe patch body is:\n\n```\n$ARGUMENTS[0]\n```\n","frontmatter":{"name":"adapters-critic","description":"Use in a reviewer agent in agent loops or when reviewing your own code.","when_to_use":"Use before editing any code in Adapters or related crates.","argument":["tentative-edit"],"context":"fork","allowed-tools":"Bash(git log *) Bash(git diff *) Bash(grep) Bash(ls) Bash(cat)","allowedTools":["Bash(git","log","*)","Bash(git","diff","*)","Bash(grep)","Bash(ls)","Bash(cat)"]},"allowedTools":["Bash(git","log","*)","Bash(git","diff","*)","Bash(grep)","Bash(ls)","Bash(cat)"],"isInternal":false,"tokens":2288,"sizeBytes":9462}],"systemPromptSnippet":"<yakaai_skills repo=\"dbt-labs/dbt-core\">\n<!-- File: AGENTS.md (Tokens: ~1149 | Category: root-instruction) -->\n# Project Instructions (AI Agents)\n\nThese instructions are for coding agents (Codex CLI, Claude Code, etc).\n\nPaths in this file and in `.agents/` are relative to the directory containing this file.\n\n## Hard Rules\n\n### Code Style\n\n- Follow existing code style and patterns in the given crate/module.\n- Keep changes minimal and focused to the task at hand.\n- Prefer simple, readable code over clever or complex solutions.\n\n### Changelog\n\n- Never manually create or write changelog YAML files. Always use `changie new` to generate entries.\n- Run `changie new` from the repository root with flags: `changie new --kind \"<kind>\" --body \"<description>\" --custom \"project=<project>\" --custom \"issue=<number>\" --custom \"author=<handle>\" --interactive=false`\n- For optional empty fields (`issue`, `author`), prompt the user if running locally or pass a space (e.g., `--custom \"issue= \"`) then edit the generated file to replace `' '` with `\"\"`.\n\n### Logging and printing\n\n- Never call `tracing::{error,warn,info,debug,trace}!` or `tracing::event!`, and never use `println!`/`eprintln!`/`print!`/`eprint!`. This includes debug-only and internal code.\n- Emit a structured event if one exists (`LogMessage`, `ProgressMessage`, ...). Otherwise use the level helper in `dbt_common::tracing::dbt_emit`: `emit_error_log_message`, `emit_warn_log_message`, `emit_info_log_message`, `emit_debug_log_message`, `emit_trace_log_message`.\n- Only for output strictly to the CLI with no trace: `dbt_emit::print_err` instead of `eprintln!`, `dbt_emit::print`/`println` instead of `print!`/`println!`.\n- Why: the emit helpers use `#[track_caller]` to record the call site and pass telemetry attributes through thread-local storage, and their events are exported to OTEL. The macros bypass both.\n- Create spans with `create_info_span`/`create_debug_span` (`dbt_tracing::emit`), not `tracing::span!`. `#[tracing::instrument]`, `tracing::Instrument` and `Span::current()` are fine.\n- Exceptions to the print ban: `build.rs` (`println!(\"cargo:...\")` directives), tests, and `xtask`/dev tooling (`crates/xtask`, `dbt-ci`, `examples/`, `benches/`).\n- Details: `.agents/telemetry-tracing.md`.\n\n### Error codes\n\n- Never use `ErrorCode::Generic` in new code. It carries no signal about what went wrong.\n- Use `ErrorCode::Unexpected` only for a true internal inconsistent state, meaning an invariant the code itself broke. Never use it for errors caused by user input, config, project files, or the warehouse.\n- Otherwise use the most specific existing `ErrorCode`, or add a new one in `crates/dbt-error/src/codes.rs` (CLI codes `[1000, 8999]`, internal `[9000, 9899]`; frontend codes come from `dbt_frontend_common::error::ErrorCode`, don't add them here).\n- Why: codes `>= 9000` are reported as Fusion bugs (`ErrorCode::is_bug`), so misusing `Unexpected` inflates bug counts and hides the real cause. User-facing codes (`dbtNNNN`) tell users what to fix, and `warn_error_options` targets codes, so a shared code makes users promote or silence unrelated warnings. Give each new warning its own code.\n- Existing `Generic`/`Unexpected` sites are legacy; don't copy them.\n\n### Running dev commands\n\n- Never run blanket `cargo` commands without `-p <crate>` unless explicitly asked.\n- Avoid context pollution: don’t paste long logs; prefer LLM-friendly JSONL output and short excerpts.\n- Avoid full builds and full test runs during iteration; keep commands scoped and fast.\n\n## Where To Look Next (Task-Specific)\n\n- Respect author preferences (optional/local): `AGENTS.local.md`\n- When writing, running or recording adapter record/replay tests (end-to-end tests against a warehouse): `crates/dbt-sa-adapter-tests/README.md`\n- When working on Adapters: `.agents/adapters.md`. Adapters consist of the following crates:\n  - `dbt-adapter`\n  - `dbt-adapter-core`\n  - `dbt-adapter-sql`\n  - `dbt-auth`\n  - `dbt-sql-keywords`\n  - `dbt-adbc`\n- When working on telemetry/tracing: `.agents/telemetry-tracing.md`\n- When working on dbt-docs-server (static site + DuckDB-WASM in the browser): `.agents/dbt-docs-server.md`\n- When adding, graduating, or removing a feature flag or behavior flag, or reading one at a call site: declare it in `crates/dbt-flags/src/catalog.rs`; precedence and stages are documented in `crates/dbt-flags/src/lib.rs`. Do not add new `std::env::var` toggles or `project_flags_get_value` lookups for this.\n- Always check for nested `AGENTS.md` files in subdirectories you modify\n- If context is not enough, try reading repo overview / architecture as last resort: `README.md`\n\n<!-- File: .agents/skills/adapters-annotate-references/SKILL.md (Tokens: ~1366 | Category: anthropic-skill) -->\n---\nname: adapter-skills-annotate-references\ndescription: Use when annotating fs adapter implementations with upstream dbt-adapters Python reference links. Triggers whenever you need to add or audit GitHub permalink comments in adapter_impl.rs, trace an fs adapter method back to its Python origin in dbt-adapters, or when working on adapter divergence and want to know where a method came from. Also use when asked to \"annotate references\", \"add upstream links\", or \"link adapter methods\".\n---\n\n# Adapter Skills: Annotate References\n\nWalks the Python `@available` method chain (`BaseAdapter → SQLAdapter → [Platform]Adapter`) and\nannotates the corresponding Rust `pub fn` methods in `adapter_impl.rs` with permanent upstream\nGitHub links. Methods present in Python but absent in Rust are written to a gap report.\n\n## Background\n\n`fs` implements adapter methods in Rust, drawing from the Python inheritance chain:\n\n```\nBaseAdapter  (dbt-adapters/src/dbt/adapters/base/impl.py)\n  └── SQLAdapter  (dbt-adapters/src/dbt/adapters/sql/impl.py)\n        └── PlatformAdapter  (dbt-{bigquery,snowflake,redshift,spark}/src/dbt/adapters/{platform}/impl.py)\n```\n\nThe dbt-adapters repo is a **monorepo** (Snowflake, BigQuery, Redshift, Spark, Postgres, Athena,\nplus the base and SQL layers). Databricks lives in a **separate** repo.\n\n`@available` (and variants `@available.parse_list`, `@available.parse_none`, `@available.parse(…)`)\nmarks methods exposed to the Jinja environment. Starting from Python guarantees full coverage,\nincluding platform-specific methods that only exist in one adapter's `impl.py`.\n\n---\n\n## Step 0 — Gather configuration\n\nAsk the user two questions:\n\n1. **Local path to the dbt-adapters checkout** (the dbt-labs monorepo):\n   > What is the local path to your dbt-adapters checkout? (e.g. `~/code/dbt-adapters`)\n\n2. **Any other adapter repos to include?** (comma-separated, optional):\n   > e.g. `~/code/dbt-databricks` — leave blank if none\n\nThe gap report defaults to `missing_adapter_methods.md` at the repo root.\n\n---\n\n## Step 1 — Run the reverse annotation script\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/annotate.py \\\n    --adapter-impl <path/to/adapter_impl.rs> \\\n    --dbt-adapters <dbt-adapters-path> \\\n    --all-adapters \\\n    [--extra-repos <path1>,<path2>,...] \\\n    [--missing-out missing_adapter_methods.md] \\\n    [--dry-run]\n```\n\nAlways pass `--all-adapters` to scan the full monorepo. Use `--extra-repos` for repos outside\nit (e.g. dbt-databricks). Use `--dry-run` to preview without writing.\n\nThe script:\n1. Enumerates all `@available` methods across every `*impl.py` in the provided repos.\n2. Scans `adapter_impl.rs` for `pub fn` methods.\n3. For methods **found in Rust, not yet annotated** → inserts `/// ClassName <url>`.\n4. For methods **not found in Rust** → records them in the gap report.\n5. Prints a JSON summary to stdout: `{annotated, already_annotated, missing_from_rust, …}`.\n\n---\n\n## Step 2 — Review the results\n\n**Annotations:** spot-check a few inserted lines:\n```rust\n/// BigQueryAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-bigquery/src/dbt/adapters/bigquery/impl.py#L42\npub fn load_dataframes(\n```\n\n**Gap report** (`missing_adapter_methods.md`): rendered in canonical adapter order — Snowflake,\nBigQuery, Redshift, Spark, Postgres, Athena, then any extra repos (e.g. Databricks), then\nBase / SQL Adapter. Adapters with full coverage show ✅. Share the report with the user and\ndecide whether any missing methods need follow-up porting work.\n\n---\n\n## Annotation format\n\n```\n/// <ClassName> <github-permalink>\n```\n\n**Placement** (handled automatically):\n- No existing `///` block → insert above the first `#[…]` attribute (or above `pub fn` directly).\n- Existing `///` block → append after its last line, with a blank `///` separator if needed.\n\n```rust\n// No prior doc comment:\n/// BaseAdapter https://github.com/dbt-labs/dbt-adapters/blob/<sha>/dbt-adapters/src/dbt/adapters/base/impl.py#L862\n#[tracing::instrument(…)]\npub fn get_missing_columns(\n\n// Existing doc comment:\n/// Returns columns present in source but absent in target.\n///\n/// BaseAdapter https://…/base/impl.py#L862\npub fn get_missing_columns(\n```\n\nThe class name prefix (`BaseAdapter`, `SQLAdapter`, `SnowflakeAdapter`, …) tells readers at a\nglance which level of the hierarchy the method comes from.\n\n---\n\n## Step 3 — Verify\n\n```bash\ncargo check -p dbt-adapter\ncargo nextest run -p dbt-adapter\n```\n\n---\n\n## Per-method lookup\n\nTo investigate a single method's upstream origin:\n\n```bash\npython3 .agents/adapter-skills-annotate-references/scripts/find_upstream.py \\\n    <method_name> <dbt-adapters-path> \\\n    [--adapter-type <type>] \\\n    [--extra-repos <path>]\n```\n\nReturns JSON with `found`, `best` (lowest-priority = most specific match), `all_matches`, and\n`non_available_matches`. Only `@available`-decorated methods appear in `all_matches`; the rest\nare in `non_available_matches` for debugging. When `found: false`, skip — no annotation needed.\n\n---\n\n## Notes\n\n- `///` doc comment → method-level upstream link (what this skill adds)\n- `//` inline comment → within-body line notes (leave as-is)\n- Scripts use the current git SHA for stable permalinks; never use `main`-based URLs.\n- Monorepo package URLs are repo-root-relative: `dbt-bigquery/src/…`, `dbt-adapters/src/…`\n\n<!-- File: .agents/skills/adapters-critic/SKILL.md (Tokens: ~2288 | Category: anthropic-skill) -->\n---\nname: adapters-critic\ndescription: Use in a reviewer agent in agent loops or when reviewing your own code.\nwhen_to_use: Use before editing any code in Adapters or related crates.\nargument: [tentative-edit]\ncontext: fork\nallowed-tools: Bash(git log *) Bash(git diff *) Bash(grep) Bash(ls) Bash(cat)\n---\n\n# Your task\n\nYou are a code critic agent: your job is to find flaws in code written by other agents or humans, according to the project's intended architecture principles.\n\nStep by step review process follows.\n\n## Load the patch\n\nIf the patch body:\n- Is empty, use `git diff HEAD` instead\n- Is a path to a file, read that file and use the contents instead\n- Is a verbatim git patch, use it as-is\n\n## Identify which adapter is being worked on\n\nUsually, a patch relates to a specific `AdapterType`, like `DuckDB`, `Bigquery` or `Snowflake`.\n\nIdentify which one we're talking about. From now on, we'll refer to that as `FoofingAdapter` (or `foofing`).\n\n\n## Code review\n\nYou will perform a few sub-steps, each looking for a specific pattern or code smell that is considered bad according to the architecture goals. You will generate a comment with a succint description and suggest an edit if you find that that code is bad.\n\nThese are the substeps:\n\n### Code review - step 1: Find duplicated code\n\nLook for code that is a plain copy of other code, for example\n```\nfn my_function() {\n    // ...\n    if adapter_type == AdapterType::FoofingAdapter {\n        // duplicate code, just added a wrapper call\n        return a(b(c));\n    }\n    b(c)\n}\n```\n\nSuggest compressing the code so that it works generically across platforms. In the example above, you'd suggest sharing as most of the code paths as possible, by sharing the call to `b(c)` and not just copying it\n```\nfn my_function() {\n    // ...\n    let result = b(c);\n    let result = match adapter_type {\n        AdapterType::FoofingAdapter => a(result),\n        _ => {},\n    }\n    result\n}\n```\n\nAnother example of bad code:\n```\nlet relation = match adapter_type {\n    AdapterType::FoofingAdapter => Relation::new(adapter_type)\n            .with_quoting(Policy::trues()),\n    AdapterType::Another => Relation::new(adapter_type)\n            .with_quoting(Policy::falses()),\n}\n```\n\nReplace with a single callsite to `new()` and `with_quoting()`\n```\nlet quoting = match adapter_type {\n    AdapterType::FoofingAdapter => Policy::trues(),\n    AdapterType::Another => Policy::falses(),\n};\nlet relation = Relation::new(adapter_type).with_quoting(quoting);\n```\n\n### Code review - step 2: Avoid target-specific free functions\n\nLook for platform-specific free functions, structs or enums outside of platform-specific modules, this is a red flag. Code such as the following should be avoided in generic modules:\n```\nenum ClickhouseSomething {\n   // ...\n}\n\nstruct FabricSomethingElse {\n   // ...\n}\n\nfn foofing_do_something() {\n}\n\nfn duckdb_foo_bar() {\n}\n\nfn lala_bigquery_lele() {\n}\n\nfn do_something_in_snowflake() {\n}\n```\n\nIn generic modules such as `relation_impl.rs`, `adapter_impl.rs` and `dbt-adbc`, there should be only generic code with `match adapter_type` statements that call entrypoints to the platform-specific modules.\n\nSuggest replacing with something along the lines of:\n\n```\n// In the `foofing` module\nfn foofing_do_something() {\n    // platform-specific code goes here\n}\n\n// In the generic module\nuse crate::submodule::foofing::foofing_do_something()\n\nfn do_something() {\n    match adapter_type {\n        AdapterType::FoofingAdapter => foofing_do_something(),\n        AdapterType::Bigquery => panic!(\"Bigquery does not support do_something()\")\n        _ => unimplemented!(\"do_something() unimplemented for this adapter_type\")\n    }\n}\n```\n\nNote that it is OK to do `panic!()` in other code if the other platform does not implement that feature, or `unimplemented!()` if we haven't done it for that platform yet.\n\n**Real example:** `adapter/mod.rs` used to register two Jinja-dispatched entrypoints, each hardcoded to one Snowflake relation type, sitting right next to `describe_relation` — a generic, adapter-agnostic name already used by BigQuery:\n\n```rust\n\"describe_dynamic_table\" => self.describe_dynamic_table(state, args),\n\"describe_interactive_table\" => self.describe_interactive_table(state, args),\n```\n\nFixed (PR #13201, following up on #12664 review feedback) by keeping one Jinja-facing name and dispatching internally on adapter type and relation type, instead of on the Jinja method name:\n\n```rust\nif adapter.adapter_type() == AdapterType::Snowflake {\n    match relation.relation_type() {\n        Some(RelationType::DynamicTable) => adapter.describe_dynamic_table(/* ... */),\n        Some(RelationType::InteractiveTable) => adapter.describe_interactive_table(/* ... */),\n        other => Err(minijinja::Error::new(\n            minijinja::ErrorKind::InvalidOperation,\n            format!(\"describe_relation is not supported for relation type {other:?} on Snowflake\"),\n        )),\n    }\n} else {\n    Ok(adapter.describe_relation(conn.as_mut(), &relation, Some(state))?\n        .map(Value::from_object)\n        .unwrap_or_else(none_value))\n}\n```\n\nThe old per-type Rust methods stayed as private helpers called from the match arms — only the Jinja-facing dispatch surface needed to become generic, not the method bodies themselves.\n\n### Code review - step 3: No SQL-processing utilities outside of `dbt-adapter-sql` or `dbt-adapter-keywords`\n\nIf you find SQL keyword normalization/sanitization, statement splitting, keyword detection etc outside of the `dbt-adapter-sql` and `dbt-adapter-keywords` crates, suggest moving those there. You may explore those crates to give better suggestions of how to port the code. Example code that should live in these crates.\n\n```\nfn format_identifier() {\n    // do SQL identifier formatting\n}\n\nfn sanitize_identifier() {\n    // do SQL identifier sanitization\n}\n\nfn requires_quotes() {\n    // check if an identifier requires quotes\n}\n```\n\nIf those are free functions, apply the same rules as in \"step 2\" and suggest a generic function that does `match adapter_type`. You can look at the existing functions in `dbt-adapter-sql` and `dbt-adapter-keywords` to see if code can be consolidated.\n\n\n### Code review - step 4: Replace `if adapter_type` with `match`\n\nWhat to look for:\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n    return;\n}\n// generic code\n```\n\n```\nif adapter_type == AdapterType::FoofingAdapter {\n    // target-specific code \n} else {\n    // generic code\n}\n```\n\nSuggest replacing with:\n\n```\nmatch adapter_type {\n    AdapterType::FoofingAdapter => {\n        // target-specific code\n    }\n    _ => {\n        // generic code\n    }\n}\n```\n\n### Code review - step 5: No useless comments\n\nFind obvious comments that directly comment what the following code does, for example\n```\nlet db = match adapter_type {\n    // THE COMMENT BELOW IS BAD\n    // database is uppercased in Foofing\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nInstead, suggest simply deleting the the comment:\n```\nlet db = match adapter_type {\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\nThe one exception is if the comment carries meaningful information that is not expressed in the code. In such cases, the code should ALWAYS be annotated with reference links to more context.\n\nFor example, the following comment is okay:\n```\nlet db = match adapter_type {\n    // For historical reasons, Foofing does database uppercasing to avoid identifier conflicts when foo bars.\n    // Original Python adapter implementation: <link to python code>\n    // Documentation for Foofing identifier matching: <link to python code>\n    AdapterType::Foofing => raw_db.to_uppercase(),\n    _ => raw_db.to_uppercase(),\n}\n```\n\n### Code review - step 6: Final questions\n\nAsk yourself: \n- Does this function/struct/enum belong here? Is there any other code in the codebase that does the same/similar thing? Where does that code live? Consider whether that might be a more appropriate module for that code.\n- Are there any free functions returning booleans that drive one-off control flow? That is bad.\n\n## Output\n\nAfter gathering all the steps above, you will output your findings in markdown consisting of \"header with short explanation, file:lineno, patch\". DO NOT output your reasoning or long prose, only the necessary patch, file name/line number and a SHORT, succint description. \n\nFor example, the output should look like:\n\n<example>\n# replace `if adapter_type` with match\n\nBEFORE: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nif adapter_type == AdapterType::Foofing {\n  the_code()\n} else {\n  other_code()\n}\n```\n\nAFTER: `crates/my-crate/src/my/file.rs:1234-1237`\n```\nmatch adapter_type {\n  AdapterType::Foofing => the_code(),\n  _ => other_code(),\n}\n```\n\n# move `foofing_do_something()` to `my_module::foofing()`\n\nBEFORE: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nfn foofing_do_something() {\n    // the code\n}\n```\n\nAFTER: `crates/my-crate/src/generic_file.rs:1234-1237`\n```\nuse my_module::foofing;\n\nfn do_something(adapter_type: AdapterType) {\n    match adapter_type {\n        AdapterType::Foofing => foofing::do_something(),\n        _ => unimplemented!(),\n    }\n}\n```\n\nAFTER: `crates/my-crate/src/my_module.rs`\n```\nfn do_something() {\n    // the code\n}\n```\n</example>\n\n\n# Time to execute\n\nInstructions done. Go execute.\n\nThe patch body is:\n\n```\n$ARGUMENTS[0]\n```\n</yakaai_skills>"}