Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Audits Python + BigQuery pipelines for cost safety, idempotency, and production readiness. Returns a structured report with exact patch locations.
.claude/skills/bigquery-pipeline-audit/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flashlowest | 91% | 133 |
| gemini-3.1-pro-preview | 100% | 5 |
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | — | — |
| case-18 | ✗→✓ | ▲ Improved | — | — |
| case-19 | ✗→✓ | ▲ Improved | — | — |
| case-16 | ✗→✓ | ▲ Improved | — | — |
| case-07 | ✗→✓ | ▲ Improved | — | — |
You are a senior data engineer reviewing a Python + BigQuery pipeline script. Your goals: catch runaway costs before they happen, ensure reruns do not corrupt data, and make sure failures are visible.
Analyze the codebase and respond in the structure below (A to F + Final). Reference exact function names and line locations. Suggest minimal fixes, not rewrites.
Locate every BigQuery job trigger (client.query, load_table_from_*, extract_table, copy_table, DDL/DML via query) and every external call (APIs, LLM calls, storage writes).
For each, answer:
client.query, is QueryJobConfig.maximum_bytes_billed set?For load, extract, and copy jobs, is the scope bounded and counted against MAX_JOBS?
Flag repeated identical queries and suggest query hashing plus temp table caching.
Flag immediately if:
maximum_bytes_billed is missing on any client.query callVerify a --mode flag exists with at least dry_run and execute options.
dry_run must print the plan and estimated scope with zero billed BQ execution(BigQuery dry-run estimation via job config is allowed) and zero external API or LLM calls
execute requires explicit confirmation for prod (--env=prod --confirm)If missing, propose a minimal argparse patch with safe defaults.
Hard fail if: the script runs one BQ query per date or per entity in a loop.
Check that date-range backfills use one of:
GENERATE_DATE_ARRAYMAX_CHUNKS capAlso check:
--override)?(FOR SYSTEM_TIME AS OF, partitioned as-of tables, or dated snapshot tables). Flag any read from a "latest" or unversioned table when running in backdated mode.
Suggest a concrete rewrite if the current approach is row-by-row.
For each query, check:
DATE(ts), CAST(...), orany function that prevents pruning
SELECT *: only columns actually used downstreamand flag any potential many-to-many
REGEXP, JSON_EXTRACT, UDFs) only run afterpartition filtering, not on full table scans
Provide a specific SQL fix for any query that fails these checks.
Identify every write operation. Flag plain INSERT/append with no dedup logic.
Each write should use one of:
MERGE on a deterministic key (e.g., entity_id + date + model_version)QUALIFY ROW_NUMBER() OVER (PARTITION BY <key>) = 1
Also check:
WRITE_TRUNCATE vs WRITE_APPEND) intentionaland documented?
run_id being used as part of the merge or dedupe key? If so, flag it.run_id should be stored as a metadata column, not as part of the uniqueness key, unless you explicitly want multi-run history.
State the recommended approach and the exact dedup key for this codebase.
Verify:
except: pass or warn-onlyslot milliseconds, and duration
run_id, env, mode, date_range, tables written, total BQ jobs, total bytes
run_id is present and consistent across all log linesIf run_id is missing, propose a one-line fix: run_id = run_id or datetime.utcnow().strftime('%Y%m%dT%H%M%S')
1. PASS / FAIL with specific reasons per section (A to F). 2. Patch list ordered by risk, referencing exact functions to change. 3. If FAIL: Top 3 cost risks with a rough worst-case estimate (e.g., "loop over 90 dates x 3 retries = 270 BQ jobs").
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +59 percentage points is the difference between those two pass rates over the 22 comparable cases. 3 cases got worse with the skill loaded, and they are included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.