Summary
Add a new CLI command check-config-keys that scans a dbt project's dbt_project.yml and schema YAML files, identifies both property keys and config keys not present in the Fusion JSON schema, and suggests the closest valid key where a misspelling is likely.
This command acts as a pre-check before running autofix — surfacing human errors (typos, wrong separators) that deterministic fixes can't catch on their own.
Motivation
The manual_fixes/misspelled_config_keys.md guidance today is purely documentation for AI agents. This feature brings that logic into the CLI itself, giving all users a fast, deterministic tool to catch config key mistakes before they cause Fusion parse failures.
Proposed command
dbt-autofix check-config-keys [--path PATH] [--json]
Example output:
myproject/dbt_project.yml:14 unknown key 'materailized' — did you mean 'materialized'?
myproject/models/staging/_schema.yml:7 unknown key 'pre_hook' — did you mean 'pre-hook'?
myproject/models/staging/_schema.yml:9 unknown key 'desciption' — did you mean 'description'?
myproject/models/marts/_schema.yml:22 unknown key 'snowflake_warehose' — did you mean 'snowflake_warehouse'?
myproject/models/marts/_schema.yml:31 unknown key 'custom_owner' — no close match found (consider moving to meta:)
Design
Schema source: Fusion CDN schemas (same source as the deprecations command), via the existing SchemaSpecs class in retrieve_schemas.py. No new schema fetching infrastructure needed.
Similarity algorithm: Two-stage normalized Levenshtein
- Normalize first — strip
+ prefix, unify -/_ separators → check for exact match (catches separator confusion for free, zero false positives)
- Levenshtein distance with proportional threshold (
max(1, len(key) // 7)) on the remainder — short keys require near-exact match, long keys get more slack
Key sets checked per node in yml files (two layers):
- Property keys (top-level node keys like
description, name, constraints) → SchemaSpecs.yaml_specs_per_node_type[node_type].allowed_properties
- Config block keys (keys inside
config:) → SchemaSpecs.yaml_specs_per_node_type[node_type].allowed_config_fields
dbt_project.yml config keys → SchemaSpecs.dbtproject_specs_per_node_type[node_type].allowed_config_fields_dbt_project
Relationship to existing work
This feature fully addresses #9. That issue identified that misspelling detection is currently limited to a hardcoded dict in src/dbt_autofix/refactors/constants.py:
COMMON_PROPERTY_MISSPELLINGS — only catches 4 variants of description
COMMON_CONFIG_MISSPELLINGS — only catches post-hook/pre-hook separator confusion
These are used in the deprecations command today: if a key matches the hardcoded dict it gets renamed, otherwise it is silently moved to meta. The new command replaces the guesswork with a dynamic, schema-driven similarity check across the full set of valid keys.
Future opportunity: upgrade the deprecations command
Once the similarity algorithm exists as a standalone module (key_similarity.py), the deprecations changeset logic in dbt_schema_yml.py and dbt_sql.py could be upgraded to use it instead of the static dicts — making autofix itself smarter about what it renames vs. what it moves to meta. This is intentionally out of scope for this issue but is a natural follow-on.
Implementation plan
Phase 1 — Foundation (parallel)
- 1B
src/dbt_autofix/key_similarity.py — pure similarity functions (normalize_key, levenshtein_distance, find_closest_match)
- 1C
tests/unit_tests/test_key_similarity.py — unit tests (exact match after normalization, transpositions, separator confusion, short-key false-positive guard, long keys)
Phase 2 — Scanner (depends on Phase 1)
- 2A
src/dbt_autofix/config_key_checker.py — walks project files, checks both property keys and config block keys against SchemaSpecs, returns (file_path, line_number, unknown_key, suggestion | None). Uses ruamel.yaml for line number preservation.
- 2B
tests/unit_tests/test_config_key_checker.py — unit tests using MockSchemaSpecs pattern from test_refactor.py
Phase 3 — CLI wiring (depends on Phase 2)
- 3A Add
@app.command(name="check-config-keys") to src/dbt_autofix/main.py. Instantiates SchemaSpecs, accepts --path/-p and --json/-j.
Phase 4 — Integration test (depends on Phase 3)
- 4A Fixture project
tests/integration_tests/dbt_projects/project_misspelled_keys/ with deliberate misspellings across both property keys and config keys
- 4B Integration test asserting expected findings
Dependency graph
1B ──► 2A ──► 3A ──► 4A ──► 4B
1C (parallel with 1B)
2B (parallel with 2A, uses MockSchemaSpecs)
Out of scope
- Auto-fixing the misspellings (that remains a manual or AI-assisted step)
- Validating value correctness (e.g. invalid enum values for
materialized)
- Upgrading the
deprecations command to use the new similarity algorithm (tracked as a future follow-on above)
Summary
Add a new CLI command
check-config-keysthat scans a dbt project'sdbt_project.ymland schema YAML files, identifies both property keys and config keys not present in the Fusion JSON schema, and suggests the closest valid key where a misspelling is likely.This command acts as a pre-check before running
autofix— surfacing human errors (typos, wrong separators) that deterministic fixes can't catch on their own.Motivation
The
manual_fixes/misspelled_config_keys.mdguidance today is purely documentation for AI agents. This feature brings that logic into the CLI itself, giving all users a fast, deterministic tool to catch config key mistakes before they cause Fusion parse failures.Proposed command
Example output:
Design
Schema source: Fusion CDN schemas (same source as the
deprecationscommand), via the existingSchemaSpecsclass inretrieve_schemas.py. No new schema fetching infrastructure needed.Similarity algorithm: Two-stage normalized Levenshtein
+prefix, unify-/_separators → check for exact match (catches separator confusion for free, zero false positives)max(1, len(key) // 7)) on the remainder — short keys require near-exact match, long keys get more slackKey sets checked per node in yml files (two layers):
description,name,constraints) →SchemaSpecs.yaml_specs_per_node_type[node_type].allowed_propertiesconfig:) →SchemaSpecs.yaml_specs_per_node_type[node_type].allowed_config_fieldsdbt_project.ymlconfig keys →SchemaSpecs.dbtproject_specs_per_node_type[node_type].allowed_config_fields_dbt_projectRelationship to existing work
This feature fully addresses #9. That issue identified that misspelling detection is currently limited to a hardcoded dict in
src/dbt_autofix/refactors/constants.py:COMMON_PROPERTY_MISSPELLINGS— only catches 4 variants ofdescriptionCOMMON_CONFIG_MISSPELLINGS— only catchespost-hook/pre-hookseparator confusionThese are used in the
deprecationscommand today: if a key matches the hardcoded dict it gets renamed, otherwise it is silently moved tometa. The new command replaces the guesswork with a dynamic, schema-driven similarity check across the full set of valid keys.Future opportunity: upgrade the
deprecationscommandOnce the similarity algorithm exists as a standalone module (
key_similarity.py), thedeprecationschangeset logic indbt_schema_yml.pyanddbt_sql.pycould be upgraded to use it instead of the static dicts — making autofix itself smarter about what it renames vs. what it moves tometa. This is intentionally out of scope for this issue but is a natural follow-on.Implementation plan
Phase 1 — Foundation (parallel)
src/dbt_autofix/key_similarity.py— pure similarity functions (normalize_key,levenshtein_distance,find_closest_match)tests/unit_tests/test_key_similarity.py— unit tests (exact match after normalization, transpositions, separator confusion, short-key false-positive guard, long keys)Phase 2 — Scanner (depends on Phase 1)
src/dbt_autofix/config_key_checker.py— walks project files, checks both property keys and config block keys againstSchemaSpecs, returns(file_path, line_number, unknown_key, suggestion | None). Usesruamel.yamlfor line number preservation.tests/unit_tests/test_config_key_checker.py— unit tests usingMockSchemaSpecspattern fromtest_refactor.pyPhase 3 — CLI wiring (depends on Phase 2)
@app.command(name="check-config-keys")tosrc/dbt_autofix/main.py. InstantiatesSchemaSpecs, accepts--path/-pand--json/-j.Phase 4 — Integration test (depends on Phase 3)
tests/integration_tests/dbt_projects/project_misspelled_keys/with deliberate misspellings across both property keys and config keysDependency graph
Out of scope
materialized)deprecationscommand to use the new similarity algorithm (tracked as a future follow-on above)