bigquery-sql
BigQuery-specific SQL patterns: UNNEST for array expansion, STRUCT, ARRAY_AGG,…
Load at Step 1 before exploring the project. Covers output shape inference, incremental model handling, and what to trust in YML.
$ npx -y skills add signalpilot-labs/signalpilot --skill dbt-workflow --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/dbt-workflowContext preview
The summary Claude sees to decide when to auto-load this skill.
Load at Step 1 before exploring the project. Covers output shape inference, incremental model handling, and what to trust in YML.
name: dbt-workflow description: "Load at Step 1 before exploring the project. Covers output shape inference, incremental model handling, and what to trust in YML." type: skill
Project-specific conventions, decisions, and quirks live in the Knowledge Base. Always consult before exploring the project.
Call once at the start of every task with a 1-line `task_description`. Returns the always-loaded baseline (org/project understanding + conventions) plus up to 5 task-relevant decisions/debugging/quirks. Treat the returned `## title` blocks as authoritative for naming, grain, and known traps.
Call when you hit something unexpected — column meaning unclear, ambiguous join, surprising row count. Pass a 2–4 word query. It is a pure read — no side effects.
Call ONLY after you have completed work and verified a finding. Use it to record:
Extract from `description:` field:
with `ROW_NUMBER() ... <= N` using a deterministic tiebreaker (add primary key to ORDER BY). Do NOT use DENSE_RANK for filtering — it can return more than N rows.
description → ONE output date (latest), not all historical dates. Filter with `WHERE date_col = (SELECT MAX(date_col) FROM source)`.
AND you are writing this model from scratch (stub/missing), the comparison column must be `CAST(NULL AS DOUBLE)` — see rule below.
**How to read YML descriptions:** Descriptions tell you what the data MEANS, not what code to write. Use them to:
the grid" → use the `grid` column, not qualifying position)
But do NOT treat descriptions as literal computation instructions. They may describe steady-state behavior that doesn't apply on first build, or use imprecise language. After reading the description, always verify your logic against the actual source data — query the source tables to confirm which columns and values produce the expected result.
Write at top of SQL: `-- EXPECTED SHAPE: <row count or formula> — REASON: <quote>`
The starting database contains pre-computed reference tables with correct output. `dbt run` will overwrite them. **Before your first `dbt run`**, for each target model that already exists as a table in the database:
SELECT COUNT(*) FROM <model_name>
Record the row count in your `-- EXPECTED SHAPE` comment. If your rebuilt model's row count doesn't match after `dbt run`, you MUST diff against this reference to find which rows differ.
When a dbt project uses `materialized="incremental"` models, the project is designed to accumulate state over multiple runs. On a **first run** (full refresh, no prior state), incremental models build from scratch.
**If you are writing a new model that includes period-over-period metrics (MoM, WoW, YoY) and the project has not been run incrementally before**: 1. Output rows for the **latest date only**: `WHERE date_col = (SELECT MAX(date_col) FROM source)` 2. Period-over-period columns must be `CAST(NULL AS DOUBLE)` — there is no prior aggregated state to compare against. Computing these from raw historical data would produce values that don't match the expected first-run output.
**If the model SQL already exists** (not a stub):
**Trust YML for**: column names (exact match required), column descriptions (what each column represents), ref dependencies (what tables to join).
**YML `not_null` tests on key/dimension columns** (IDs, names, dates, categories) imply a `WHERE col IS NOT NULL` filter on input data. Do NOT implement this as an INNER JOIN — use an explicit WHERE clause. `not_null` on metric/aggregate columns (counts, averages, totals) just asserts the output shouldn't be NULL — don't filter inputs for those, fix the aggregation instead.
**Do NOT trust YML for**: grain/row count. YML `unique` and `not_null` tests are assertions that may be aspirational or wrong. Do NOT use `not_null` tests to decide join type.
Derive the grain from these signals (in priority order):
1. **Unique key structure**: If the YML defines a unique key or surrogate key column, examine what it's composed of. A key like `concat(ticker, timestamp)` means the grain is (ticker, timestamp) — not (ticker, date). The key tells you exa
Repo: signalpilot-labs/signalpilot
BigQuery-specific SQL patterns: UNNEST for array expansion, STRUCT, ARRAY_AGG,…
Load when dbt run or dbt parse fails. Covers YML duplicate patches, ref errors, passthrough…
Populate the knowledge base from dbt project research. Proposes entries across all 6…
Load when task involves dbt snapshots, SCD Type 2, or tracking data changes over time. Covers…
Load when task involves adding, writing, or fixing dbt unit tests. Covers unit_tests YAML…
Load when task involves dbt model versioning, creating v2 of a model, or backward-compatible…