Review Spell PR
Use this skill when reviewing a Spellbook spell contribution (new model or modification). Walk through each section below as a checklist.
1. Config Block
-
schemais present and correct for the Dune namespace -
aliasis present and matches intended table/view name -
materializedis explicitly declared (not relying on dbt_project.yml default) - If
tableorincremental:file_format='delta'is present - If
incremental:-
incremental_strategyspecified (merge,append, ordelete+insert) -
unique_keyspecified — no columns that could contain NULLs -
incremental_predicatesuses theincremental_predicate()macro (unless full-history lookup needed) - If partitioned: partition column(s) included in
unique_key
-
- Config block formatting follows repo SQL conventions (tabs, trailing comma on last param,
{{ config(on first line)
2. Schema YML (_schema.yml)
- Model entry exists with name matching the SQL filename
- Model has a description
-
dbt_utils.unique_combination_of_columnstest present — columns match configunique_keyexactly -
not_nulltest on each unique key column - Key columns have descriptions
- For sector-level spells: seed test is present (e.g.,
check_dex_base_trades_seed)
3. SQL Style
- Leading commas (left comma club)
- Tab indentation (no spaces)
- All SQL keywords and function names lowercase
- New line after
select,from,where,group by,order by, etc. - Explicit join types (
inner join,left join— never barejoin) - Table aliases use
askeyword (from users as u, notfrom users u) - All columns prefixed with table aliases when joins are present
- CTEs use leading commas between them,
withand CTE name on same line
4. Jinja
- All table references use
source()orref()— no hardcoded table names - Jinja whitespace: trailing
-only ({% if -%},{% else -%},{% endif -%}) -
{% if is_incremental() -%}block present for incremental models with:- Incremental path using
{{ incremental_predicate('source.block_time') }} - Non-incremental path with earliest date filter
- Incremental path using
5. Performance
- Join order: larger table on left side
- Partition filters present in WHERE clauses (
block_date,block_time) - Cross-chain tables filtered by both
blockchainand time - No
SELECT *on large tables -
UNION ALLused (not bareUNION) unless deduplication truly needed - No
ORDER BYwithoutLIMITon large result sets - Time filters in both ON and WHERE clauses when joining on partition columns
6. Seed File (Sector-Level Spells)
- Seed CSV present with representative rows
- Seed registered in directory's
_schema.ymlwith column types - Seed columns include all unique key columns + fields to test
- Seed is small (handful of rows, not hundreds)
- Seed test called in model's
_schema.ymlwith correct parameters
7. Architecture (Sector-Level Spells)
- Follows lineage: platform base → chain-level union (table) → cross-chain union (view) → final enriched spell
- Platform base spells use macros for forked protocols where applicable
- One model per protocol, per version, per blockchain
- Metadata enrichment saved for downstream (base spells contain raw data only)
8. Compile & Test
Run dbt compile in the relevant sub-project to verify:
- No compilation errors
- Compiled SQL in
target/looks correct - Test with
python scripts/dune_query.py "@model_name" --limit 100or paste into Dune