Standardizing AI Output in Paradime with Dinorules (dbt™ Style Guide Enforcement)
Feb 26, 2026
Custom AI Rules for dbt™ Projects: A Pragmatic Guide to .dinorules
Every analytics engineering team that adopts AI-assisted development hits the same wall: the first few AI-generated models look great, but by the tenth pull request, your codebase is a patchwork of uppercase SELECT in one file, lowercase select in another, trailing commas here, leading commas there, and a select * quietly slipping into production.
This isn't an AI quality problem — it's a governance problem. Without custom AI rules, every AI interaction is a coin flip against your team's standards.
According to CodeRabbit's State of AI vs Human Code Generation Report, AI-generated pull requests contain 2.66× more formatting inconsistencies and ~1.7× more issues overall than human-only PRs. Readability issues spike more than 3× in AI contributions — the single biggest quality gap in the dataset.
The fix is deceptively simple: define your rules once, in a file, and let AI enforce them automatically. In this guide, we'll walk through how to use .dinorules — Paradime's custom AI rules file — to bring consistency, reviewability, and reduced PR churn to your dbt™ projects.
Why AI Output Drifts (and Why It Matters in dbt™ Repos)
Large language models don't remember your team's conventions between sessions. Each prompt starts fresh, and without explicit guidance, AI defaults to whatever patterns are most common in its training data — not what's correct for your project.
In a dbt™ repo, this drift compounds quickly.
Formatting Churn in PRs
When one AI session capitalizes SQL keywords and the next doesn't, you end up with pull requests where half the diff is cosmetic reformatting. Reviewers waste time parsing style changes instead of evaluating logic. Over time, this "formatting churn" erodes trust in AI-assisted development:
Figure 1: The formatting churn loop — AI style drift creates review cycles that add zero business value.
Inconsistent Conventions Harm Maintainability
When AI generates stg_orders.sql using CTEs and stg_customers.sql using subqueries, the next engineer to touch those models has to mentally context-switch between paradigms. Multiply this across hundreds of models and you have a codebase that's technically correct but practically unmaintainable.
Common inconsistencies include:
Comma placement: trailing in some files, leading in others
Alias conventions: short aliases like
oforordersvs. full table namesCTE vs. subquery patterns: mixed across similar models
Column ordering: no consistent pattern for primary keys, foreign keys, and business columns
Risky Patterns (select *, Implicit Joins)
AI models have no inherent sense of "danger." They'll happily generate a select * that breaks downstream models when a source column changes, or produce an implicit join (comma-separated FROM clause) that makes auditing nearly impossible.
What .dinorules Is and Where It Lives
.dinorules is a plain-text file that contains natural language instructions for DinoAI, Paradime's AI engine for dbt™ development. Think of it as a .cursorrules or .windsurfrules file, but purpose-built for analytics engineering workflows.
No special syntax is required — you write rules in plain English (or bullet points, sections, numbered lists). DinoAI reads these instructions and applies them to every AI interaction in your project: generating new models, updating existing ones, writing documentation, and creating tests.
Root-of-Repo Placement
The .dinorules file must live in the root directory of your repository, alongside your dbt_project.yml:
Because .dinorules is git-tracked by default, your entire team shares the same rule set. Changes go through the same PR review process as any other code change, giving you full version history and collaborative governance.
Tip: If your team hasn't aligned on standards yet, add
.dinorulesto.gitignoretemporarily while you iterate locally. Once agreed, commit and share.
How DinoAI Reads and Applies Rules
When you interact with DinoAI — whether through inline suggestions, agent mode, or prompt-based generation — it automatically loads your .dinorules as part of its context window. There's no extra configuration or prompt engineering needed.
Figure 2: DinoAI's context pipeline — rules are loaded automatically alongside warehouse metadata on every interaction.
This means the rules compound: every new model, every documentation block, every test suggestion is filtered through your team's standards. You define the rules once, and enforcement is continuous.
For details on setting up .dinorules, see the official Paradime documentation.
A Starter .dinorules Template for dbt™ Projects
Here's a production-ready .dinorules template you can drop into your repo today. It covers the three pillars of pragmatic governance: style consistency, safety rails, and dbt™ conventions.
Let's break down each section.
SQL Style: Lowercase Keywords, Leading Commas, Explicit Join Conditions
The SQL style section removes the most common source of formatting churn. By specifying lowercase keywords and leading commas, you align with the dbt™ Labs style guide conventions and ensure clean git diff output:
Explicit join conditions eliminate ambiguity. Instead of join orders (which defaults to inner join silently), the rule forces inner join orders, making the developer's intent visible to every reviewer.
Safety: Never select *, Require WHERE Clauses on Deletes
The safety section prevents the two most dangerous patterns in dbt™ projects:
select * breaks contracts. When an upstream source adds or removes a column, select * silently propagates that change through your entire DAG. Explicitly listing columns acts as a schema contract — breakages are surfaced immediately as compilation errors, not as corrupted dashboards days later.
Unfiltered deletes are catastrophic. A DELETE without a WHERE clause can wipe a production table. While rare in dbt™ (which is primarily SELECT-based), teams using pre-hooks or operations may encounter this.
dbt™ Conventions: Use ref(), source(), and Staging Patterns
This section encodes the dbt™ best practice that source() is only used in staging models, and everything downstream uses ref(). This creates a clean lineage graph and ensures that if a source table changes, you only need to update one staging model.
The naming convention (stg_[source]__[entity]s) comes directly from dbt™ Labs' structure guide. The double underscore separates source system from entity, making it easy to identify where data originates at a glance.
Advanced Rule Sets by Team Maturity
Not every team needs the same level of governance. Over-constraining a junior team creates friction; under-constraining a mature team invites regression. Here's how to scale your .dinorules as your team grows.
Figure 3: Progressive governance — start with safety and formatting, layer on complexity as your team matures.
Beginner: Formatting + Safety Rails
For teams just starting with dbt™ or AI-assisted development, keep rules focused on preventing harm and maintaining basic readability:
This small set of rules eliminates the top formatting complaints in code review while preventing the most dangerous anti-patterns — without overwhelming a team that's still learning dbt™ fundamentals.
Intermediate: Naming Conventions and Macro Usage
Once your team has internalized basic patterns, add rules for naming consistency, documentation, and macro usage:
Advanced: Performance Patterns (Incremental Strategy, Partitioning Guidelines)
For mature teams operating at scale, add rules governing incremental model design, partitioning, and warehouse-specific optimizations:
Here's what an incremental model looks like when governed by these advanced rules:
This model follows every advanced rule: explicit strategy, unique_key, clustering, incremental predicates to limit scan on the target table, and a lookback window for late-arriving data.
How to Validate the Rules Are Working
Writing rules is step one. Proving they work is step two.
Before/After Example: Prompt and Output
The simplest validation is a before/after test. Issue the same prompt to DinoAI with and without .dinorules and compare the output.
Prompt: "Generate a staging model for the raw_orders table in the jaffle_shop source."
Figure 4: Same prompt, different output — .dinorules transforms AI output from risky to compliant.
Without .dinorules:
With .dinorules:
The difference is immediate: lowercase keywords, explicit columns, source() macro, correct file naming convention.
PR Checklist and Code Review Heuristics
Create a lightweight checklist for reviewing AI-generated PRs. This checklist should map directly to your .dinorules sections:
Check | What to Look For | Rule Section |
|---|---|---|
✅ No | Every | Safety |
✅ Explicit joins |
| SQL Style |
✅ | Non-staging models use | dbt™ Conventions |
✅ Naming matches convention |
| Naming |
✅ Incremental has | Config block includes | Performance |
✅ Tests on PKs |
| Documentation |
✅ Leading commas | Commas at the start of each line in SELECT | SQL Style |
If you find an AI-generated model consistently failing a specific check, that's a signal to tighten the corresponding rule in .dinorules.
Common Pitfalls
Even well-intentioned rule sets can backfire. Here are the three most common mistakes teams make — and how to avoid them.
Over-Constraining Outputs
The trap: You add 50 granular rules covering every edge case, and DinoAI starts producing verbose, over-commented, rigidly structured models that take longer to review than hand-written ones.
The fix: Start with 10–15 rules maximum. Focus on rules that prevent the highest-impact problems (safety, naming, core formatting). Let your team develop opinions through code review before codifying every convention.
Rule of thumb: If a rule addresses something a linter can auto-fix (like trailing whitespace), don't add it to .dinorules. Save your rule budget for semantic patterns that linters can't catch — like "always use ref() instead of direct table references."
Conflicting Rules
The trap: Over time, rules accumulate and contradict each other. For example:
DinoAI will attempt to satisfy all rules, but conflicting instructions create unpredictable output — exactly the inconsistency you're trying to eliminate.
The fix: Treat .dinorules as code. Review it periodically as a team. Use clear section headers and avoid restating rules from external style guides unless you're choosing a specific interpretation. If you reference an external guide, note which specific conventions you're overriding:
Keeping Rules Updated as Standards Evolve
The trap: You write .dinorules once in Q1, and by Q3 your team has adopted new patterns (microbatch incremental strategy, new macro libraries) that the rules don't reflect. New AI-generated models follow outdated conventions.
The fix: Schedule a quarterly .dinorules review. Treat it like a retro:
Audit recent PRs — which review comments keep recurring? Those are candidates for new rules.
Remove rules nobody follows — if a rule creates more exceptions than compliance, delete it.
Update for new capabilities — when dbt™ releases features (like microbatch incremental models), add corresponding rules.
You can even use DinoAI's agent mode to auto-generate updated rules by pointing it at your most recent, highest-quality model files as examples of current best practice.
Figure 5: Quarterly .dinorules maintenance loop — treat your AI rules like living documentation.
Conclusion
Custom AI rules aren't about restricting what AI can do — they're about focusing what AI does on your team's actual standards. A well-crafted .dinorules file transforms AI from a formatting wildcard into a consistent, standards-aware teammate.
The approach is pragmatic: start with the starter template, validate with before/after testing, evolve with your team's maturity. The result is fewer formatting-only PR comments, more consistent model patterns, and AI-generated code that reviewers can trust.
Ready to get started? Drop the starter template from this guide into your repo root, customize the project context section, and run your next DinoAI prompt. The difference shows up in the very first model.


