Skip to content

Commit ee96869

Browse files
docs: tighten READMEs and make the dbt comparison accurate and fair (#737)
Reduce density and AI-speech tells across the four READMEs, and rework the dbt comparison so it holds up to scrutiny. - Move the root README's comparison table below the demos into a "How it compares to dbt Core" section so it no longer leads. - Fix debunktable cells: dbt Core has model contracts (1.5+) and dbt retry (1.6+); replace snark with neutral architectural distinctions. - Header is now "What dbt Core does"; split the Fusion OSS engine from dbt's paid platform; note that dbt Core defined this category. - Drop the year-stale Fusion beta date (still in public beta as of 2026-04). - Collapse repeating intro paragraphs; tighten the seven trust dimensions. - Sweep em-dash overuse (39->1 in the root README), triple-rhythm fragments, and balanced-antithesis flourishes.
1 parent d744f1f commit ee96869

4 files changed

Lines changed: 78 additions & 80 deletions

File tree

README.md

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,14 @@
1212

1313
**Rocky is the typed graph between your code and whichever warehouse, table format, or query engine you've chosen.**
1414

15-
Not a warehouse. Not a table format. Not a query engine. The trust plane for your data — a typed compiler, named branches, deterministic replay, column-level lineage, compile-time contracts, and per-model cost — running over your existing Databricks / Snowflake / BigQuery / DuckDB. Apache 2.0.
15+
It is a typed compiler that runs over your existing Databricks, Snowflake, BigQuery, or DuckDB and owns the graph between your code and your data: named branches, deterministic replay, column-level lineage, compile-time contracts, and per-model cost. Storage and compute stay where they are, and Rocky works on the SQL you already have. The `.rocky` DSL is there when you want it. Apache 2.0.
1616

17-
Rocky exists because the disasters that cost data teams real money — silent schema drift wrecking a revenue dashboard, a column rename quietly poisoning 47 downstream models, an auditor asking who touched `fct_revenue.amount` and when, a cost spike that no one can attribute to a model — all share a common shape. They're problems the warehouse can't see and the templating engine on top of it was never asked to. Rocky owns the graph between your code and the warehouse so those problems become compile errors, blocked PRs, and verifiable artifacts instead of pages and post-mortems.
18-
19-
It's built for the team running production-critical multi-tenant pipelines on Databricks today, on Snowflake or BigQuery tomorrow, who can't tolerate another silent failure. Storage and compute stay where they are. **Rocky works on the SQL you already have** — the `.rocky` DSL is an acceleration when you want it, not a gate.
17+
The failures that cost data teams the most are invisible to the warehouse and out of scope for the templating layer above it: schema drift, column-rename blast radius, dialect divergence, cost spikes nobody can attribute. Rocky turns them into compile errors and blocked PRs.
2018

2119
<p align="center">
2220
<img src="docs/public/demo-quickstart.gif" alt="Rocky quickstart — create a project, compile, and run 3 models in under 15s" width="900" />
2321
</p>
2422

25-
## The disasters Rocky prevents
26-
27-
| Disaster | What dbt does | What Rocky does |
28-
|---|---|---|
29-
| Upstream changes a column type | Silent — fails downstream, hours later | `E013` at compile, blocks the PR |
30-
| Required column dropped from a contract | No contract concept | `E010` at compile, blocks the PR |
31-
| Column rename with unknown blast radius | `dbt docs` post-hoc, table-level (dbt Cloud Enterprise has column lineage in their UI, also post-hoc, not PR-blocking) | `rocky lineage-diff` at PR time, column-level, downstream consumers listed, blocks the merge |
32-
| `SELECT *` pulls a new column you didn't expect | Silent | `P002` warning, downstream consumers named |
33-
| Snowflake-only function written for a Databricks project | Runs in dev, fails in prod | `P001` dialect-portability lint at compile |
34-
| Run cost doubles, no one knows which model | Manual warehouse spelunking | `RunOutput.cost_summary` per model, every run |
35-
| Auditor asks: who changed `fct_revenue.amount`, when, and why? | Git blame + screenshots | `rocky replay <run_id>` — content-addressed record of the exact code and the output it produced |
36-
| Sev-2 at 3 AM, half the pipeline already ran | Re-run everything | `rocky run --resume-latest` — checkpoint, three-state circuit breaker, skip what succeeded |
37-
38-
Each row is a real failure mode, with a Rocky command that turns it into a non-event. The same primitives — typed compiler, content-addressed state, column-level lineage, per-model cost — back every row.
39-
40-
**Already on dbt?** `rocky import-dbt` converts a vanilla dbt project to Rocky in one command. The "What dbt does" column above is dbt Core's behavior. **dbt Fusion** — dbt Labs' Rust rewrite of dbt Core (public beta) — catches some compile-time issues that dbt Core misses, but doesn't ship named branches, content-addressed deterministic replay, per-model cost attribution as a first-class column, dialect-portability lint across warehouses, or declarative governance + masking outside dbt platform's paid tiers. Those stay Rocky's surface, Apache 2.0.
41-
4223
## Try it in 60 seconds
4324

4425
```bash
@@ -55,27 +36,27 @@ cd my-first-project
5536
rocky compile && rocky test && rocky run
5637
```
5738

58-
No credentials needed the playground runs end-to-end on local DuckDB.
39+
No credentials needed; the playground runs end-to-end on local DuckDB.
5940

6041
## Who Rocky is for
6142

62-
Rocky is built first for **data platform engineers running production-critical, multi-tenant pipelines on Databricks** — the team that's hit dbt's ceiling, where silent failures cost real money, and where Dagster is already the orchestrator. That's the launch wedge, and that's where Rocky is most battle-tested.
43+
Rocky is built first for **data platform engineers running production-critical, multi-tenant pipelines on Databricks**, where silent failures cost real money and Dagster is already the orchestrator. That is the launch wedge, and where Rocky is most battle-tested.
6344

64-
The next ring out: **Snowflake and BigQuery shops** currently evaluating SQLMesh, who want correctness moved to the compiler (not the planner) and prefer SQL by default over Python-first ergonomics. Adapters are Beta today; see [Where Rocky is today](#where-rocky-is-today) below.
45+
The next ring out: **Snowflake and BigQuery shops** evaluating SQLMesh, who want correctness in the compiler rather than the planner and prefer SQL by default. Adapters are Beta today; see [Where Rocky is today](#where-rocky-is-today) below.
6546

6647
## See it in action
6748

68-
Each demo below is a self-contained POC in [`examples/playground/pocs/`](examples/playground/)`cd` in, run `./run.sh`, reproduce locally.
49+
Each demo below is a self-contained POC in [`examples/playground/pocs/`](examples/playground/): `cd` in, run `./run.sh`, and reproduce it locally.
6950

7051
### Detects schema drift the moment it happens
7152

72-
A source column type changes upstream. On the next run, Rocky diffs source vs. target, drops the target, and recreates it. No silent data corruption, no dbt-style quiet divergence.
53+
A source column type changes upstream. On the next run, Rocky diffs source against target, drops the target, and recreates it. No silent data corruption.
7354

7455
<p align="center">
7556
<img src="docs/public/demo-drift-recover.gif" alt="rocky run detects source type change and recreates the target" width="900" />
7657
</p>
7758

78-
[POC `02-performance/06-schema-drift-recover`](examples/playground/pocs/02-performance/06-schema-drift-recover/)
59+
[POC: `02-performance/06-schema-drift-recover`](examples/playground/pocs/02-performance/06-schema-drift-recover/)
7960

8061
### Enforces data contracts at compile time
8162

@@ -85,7 +66,7 @@ Missing required columns, protected columns being removed, or unsafe type change
8566
<img src="docs/public/demo-data-contracts.gif" alt="rocky compile flags E010 and E013 contract violations on broken_metrics" width="900" />
8667
</p>
8768

88-
[POC `01-quality/01-data-contracts-strict`](examples/playground/pocs/01-quality/01-data-contracts-strict/)
69+
[POC: `01-quality/01-data-contracts-strict`](examples/playground/pocs/01-quality/01-data-contracts-strict/)
8970

9071
### Named branches for risk-free experiments
9172

@@ -95,7 +76,7 @@ Create a branch, run against it in an isolated schema, inspect, then drop or pro
9576
<img src="docs/public/demo-branches-replay.gif" alt="rocky branch create, run on branch, and trace column lineage downstream" width="900" />
9677
</p>
9778

98-
[POC `00-foundations/06-branches-replay-lineage`](examples/playground/pocs/00-foundations/06-branches-replay-lineage/)
79+
[POC: `00-foundations/06-branches-replay-lineage`](examples/playground/pocs/00-foundations/06-branches-replay-lineage/)
9980

10081
### Column-level lineage, not table-level
10182

@@ -105,67 +86,84 @@ Trace a single column from a downstream fact back through its aggregations, all
10586
<img src="docs/public/demo-column-lineage.gif" alt="rocky lineage --column traces fct_revenue.total back to seeds.orders.amount" width="900" />
10687
</p>
10788

108-
[POC `06-developer-experience/01-lineage-column-level`](examples/playground/pocs/06-developer-experience/01-lineage-column-level/)
89+
[POC: `06-developer-experience/01-lineage-column-level`](examples/playground/pocs/06-developer-experience/01-lineage-column-level/)
10990

11091
### AI model generation with a compile-validate loop
11192

112-
Describe what you want in plain English. Rocky generates a Rocky DSL model, compiles it, and retries on parse failure — the `Attempts: 2` line shows the loop catching a first-pass error invisibly.
93+
Describe what you want in plain English. Rocky generates a Rocky DSL model, compiles it, and retries on parse failure. The `Attempts: 2` line shows the loop catching a first-pass error.
11394

11495
<p align="center">
11596
<img src="docs/public/demo-ai-model-generation.gif" alt="rocky ai generates a .rocky model from natural language intent, Attempts: 2" width="900" />
11697
</p>
11798

118-
[POC `03-ai/01-model-generation`](examples/playground/pocs/03-ai/01-model-generation/)
99+
[POC: `03-ai/01-model-generation`](examples/playground/pocs/03-ai/01-model-generation/)
119100

120101
### PR-time blast-radius with `rocky lineage-diff`
121102

122-
Compare two git refs and get a per-changed-column readout of downstream consumers pre-rendered Markdown drops straight into a GitHub PR comment. CODEOWNERS-style review tooling can't reach this granularity without a compiled engine.
103+
Compare two git refs and get a per-changed-column readout of downstream consumers; the pre-rendered Markdown drops straight into a GitHub PR comment. CODEOWNERS-style review tooling can't reach this granularity without a compiled engine.
123104

124105
<p align="center">
125106
<img src="docs/public/demo-lineage-diff.gif" alt="rocky lineage-diff main lists added and removed columns across two models with downstream consumers per change" width="900" />
126107
</p>
127108

128-
[POC `06-developer-experience/11-lineage-diff`](examples/playground/pocs/06-developer-experience/11-lineage-diff/)
109+
[POC: `06-developer-experience/11-lineage-diff`](examples/playground/pocs/06-developer-experience/11-lineage-diff/)
129110

130111
### Classify columns, mask by environment, gate CI
131112

132-
Tag PII columns in the model sidecar; bind tags to mask strategies in `[mask]` / `[mask.<env>]`. `rocky compliance --env prod --fail-on exception` exits 1 the moment a classified column has no resolved strategya one-line CI gate against accidentally-unmasked data.
113+
Tag PII columns in the model sidecar, and bind tags to mask strategies in `[mask]` / `[mask.<env>]`. `rocky compliance --env prod --fail-on exception` exits 1 the moment a classified column has no resolved strategy: a one-line CI gate against accidentally unmasked data.
133114

134115
<p align="center">
135116
<img src="docs/public/demo-classification-masking.gif" alt="rocky compliance rolls up classification tags to mask strategies; --fail-on exception exits 1, gating CI on unmasked PII" width="900" />
136117
</p>
137118

138-
[POC `04-governance/05-classification-masking-compliance`](examples/playground/pocs/04-governance/05-classification-masking-compliance/)
119+
[POC: `04-governance/05-classification-masking-compliance`](examples/playground/pocs/04-governance/05-classification-masking-compliance/)
139120

140121
### Incremental loads with persistent watermark state
141122

142-
`strategy = "incremental"` plus a `timestamp_column` is all it takes. Rocky writes the high-water mark to the embedded state store; subsequent runs only `INSERT … WHERE timestamp > watermark`. Append 25 rows after a 500-row load run 2 still finishes in 0.2s.
123+
`strategy = "incremental"` plus a `timestamp_column` is all it takes. Rocky writes the high-water mark to the embedded state store, and subsequent runs only `INSERT … WHERE timestamp > watermark`. Append 25 rows after a 500-row load, and run 2 still finishes in 0.2s.
143124

144125
<p align="center">
145126
<img src="docs/public/demo-incremental-watermark.gif" alt="rocky run with incremental strategy: run 1 copies 500 rows; appended 25 rows; run 2 only copies the delta in 0.2s" width="900" />
146127
</p>
147128

148-
[POC `02-performance/01-incremental-watermark`](examples/playground/pocs/02-performance/01-incremental-watermark/)
129+
[POC: `02-performance/01-incremental-watermark`](examples/playground/pocs/02-performance/01-incremental-watermark/)
149130

150131
## Where Rocky is today
151132

152-
The trust primitives compiler, branches, replay, lineage, contracts, cost attributionare production-grade on Databricks. We're explicit about the rest:
133+
The trust primitives (compiler, branches, replay, lineage, contracts, cost attribution) are production-grade on Databricks. The rest is in progress:
153134

154-
- **Databricks is the production target for 2026.** Snowflake, BigQuery, and Trino adapters are Beta connection, execution, and the core run loop work, but conformance coverage is still growing. If your enterprise warehouse is Snowflake or BigQuery and you need it production-grade today, talk to us.
155-
- **AI is a growing surface, not a finished product.** The compile-validate loop (generatetype-checkauto-fix land) is real and shipped; the broader story (mass refactor across the DAG, auto-migration from a column type change, schema-aware assertion generation) is on the roadmap, not the changelog.
156-
- **Iceberg.** REST-catalog source discovery is Beta. Content-addressed writes round-trip as Iceberg through Delta UniFormshipped end-to-end (Wave 2). First-class Iceberg-native writes without the Delta intermediate are on the 2026 roadmap.
135+
- **Databricks is the production target for 2026.** Snowflake, BigQuery, and Trino adapters are Beta: connection, execution, and the core run loop work, but conformance coverage is still growing. If your enterprise warehouse is Snowflake or BigQuery and you need it production-grade today, talk to us.
136+
- **AI is a growing surface, not a finished product.** The compile-validate loop (generate, type-check, auto-fix, then land) is shipped. The broader story (mass refactor across the DAG, auto-migration from a column-type change, schema-aware assertion generation) is on the roadmap.
137+
- **Iceberg.** REST-catalog source discovery is Beta. Content-addressed writes round-trip as Iceberg through Delta UniForm, shipped end-to-end. First-class Iceberg-native writes without the Delta intermediate are on the 2026 roadmap.
157138
- **No built-in semantic layer.** Rocky's typed IR is the right home for one. Today, integrate with Cube, the dbt Semantic Layer, or your existing metric store.
158-
- **Orchestration: Dagster is first-class.** A `rocky serve` standalone path exists; native Airflow / Prefect integrations are not yet shipped — they're called from the CLI like any other binary.
139+
- **Orchestration: Dagster is first-class.** A `rocky serve` standalone path exists; native Airflow and Prefect integrations are not yet shipped, so they're called from the CLI like any other binary.
140+
141+
If those gaps are blockers for your team, [open a discussion](https://github.com/rocky-data/rocky/discussions). The roadmap is shaped by where production pipelines are actually getting hurt.
142+
143+
## How it compares to dbt Core
144+
145+
| Disaster | What dbt Core does | What Rocky does |
146+
|---|---|---|
147+
| Upstream changes a column type | Silent; surfaces as a downstream failure later | `E013` at compile, blocks the PR |
148+
| Required column dropped from a contract | Caught at build time via `contract: enforced` | `E010` at compile, blocks the PR |
149+
| Column rename with unknown blast radius | `dbt docs` is post-hoc and table-level; dbt Cloud Enterprise adds column lineage in the UI, also post-hoc and not PR-blocking | `rocky lineage-diff` at PR time, column-level, downstream consumers listed, blocks the merge |
150+
| `SELECT *` pulls a new column you didn't expect | Silent | `P002` warning, downstream consumers named |
151+
| Snowflake-only function written for a Databricks project | No dialect-portability lint; runs in dev, fails in prod | `P001` dialect-portability lint at compile |
152+
| Run cost doubles, no one knows which model | No per-model cost attribution; reconstruct it from warehouse query history | `RunOutput.cost_summary` per model, every run |
153+
| Auditor asks: who changed `fct_revenue.amount`, when, and why? | Run history in dbt Cloud, but no content-addressed record of code and output | `rocky replay <run_id>`: a content-addressed record of the exact code and the output it produced |
154+
| Sev-2 at 3 AM, half the pipeline already ran | `dbt retry` resumes from the failed model; no within-run checkpoint or circuit breaker | `rocky run --resume-latest`: checkpoint, three-state circuit breaker, skip what succeeded |
155+
156+
Each row is a real failure mode and a Rocky command that turns it into a non-event. The same primitives back every row: typed compiler, content-addressed state, column-level lineage, per-model cost.
159157

160-
If those gaps are blockers for your team, [open a discussion](https://github.com/rocky-data/rocky/discussions) — the roadmap is shaped by where production pipelines are actually getting hurt.
158+
dbt Core defined this category, and `rocky import-dbt` converts a vanilla dbt project to Rocky in one command. dbt Fusion (dbt Labs' Rust rewrite of dbt Core, in public beta) closes part of the compile-time gap by type-checking SQL, though it still templates with Jinja. Neither open-source engine ships named branches, content-addressed replay, per-model cost as a first-class column, cross-warehouse dialect lint, or declarative RBAC and masking. Some governance features live in dbt's paid platform; Rocky's are open source under Apache 2.0.
161159

162160
## Subprojects
163161

164162
| Path | Artifact | Language | Description |
165163
|---|---|---|---|
166-
| [`engine/`](engine/) | `rocky` CLI binary | Rust | Core SQL transformation engine 23-crate Cargo workspace |
164+
| [`engine/`](engine/) | `rocky` CLI binary | Rust | Core SQL transformation engine, 23-crate Cargo workspace |
167165
| [`integrations/dagster/`](integrations/dagster/) | `dagster-rocky` PyPI wheel | Python | Dagster resource and component wrapping the Rocky CLI |
168-
| [`editors/vscode/`](editors/vscode/) | Rocky VSIX | TypeScript | VS Code extension LSP client + commands for AI features |
166+
| [`editors/vscode/`](editors/vscode/) | Rocky VSIX | TypeScript | VS Code extension; LSP client + commands for AI features |
169167
| [`examples/playground/`](examples/playground/) | (config only) | TOML / SQL | Self-contained DuckDB sample pipeline used for smoke tests and benchmarks |
170168

171169
Each subproject has its own README with detailed usage. The [`engine/README.md`](engine/README.md) is the canonical product reference for the Rocky CLI.
@@ -196,7 +194,7 @@ just test # runs all test suites
196194
just lint # cargo clippy/fmt + ruff + eslint
197195
```
198196

199-
`just` is optional you can also build each subproject directly. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for per-subproject build commands.
197+
`just` is optional; you can also build each subproject directly. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for per-subproject build commands.
200198

201199
## Releases
202200

@@ -210,11 +208,11 @@ See [`CONTRIBUTING.md`](CONTRIBUTING.md#releases) for the full release flow.
210208

211209
## Documentation
212210

213-
Full documentation: **[rocky-data.dev](https://rocky-data.dev)**concepts, guides, CLI reference, Dagster integration, adapter SDK.
211+
Full documentation lives at **[rocky-data.dev](https://rocky-data.dev)**: concepts, guides, CLI reference, Dagster integration, and the adapter SDK.
214212

215213
## Contributing
216214

217-
See [`CONTRIBUTING.md`](CONTRIBUTING.md). Before opening a PR, please read the cross-project change guidance schema and DSL changes must update consumers atomically.
215+
See [`CONTRIBUTING.md`](CONTRIBUTING.md). Before opening a PR, please read the cross-project change guidance: schema and DSL changes must update consumers atomically.
218216

219217
## Sponsoring
220218

0 commit comments

Comments
 (0)