Engines · Spark · DuckDB · Polars | Formats · Delta · Iceberg · DuckLake
Designed to complement, not replace, data-contract standards like ODCS. OLC adds portable execution and lakehouse engineering semantics on top. → ODCS standardises the agreement · OLC standardises the execution · the LakeLogic reference framework runs both.
One executable contract for a data product — ingest from any source, govern it, land it in an open lakehouse, publish it anywhere. Portable · SQL-native · engine-agnostic.
Your contract stays the same across every backend below — only the backend-owned execution settings (engine, table format, catalog, storage) change:
| Engines | Spark · DuckDB · Polars |
| Table formats | Delta · Iceberg · DuckLake |
| Platforms | Databricks · Snowflake · Fabric · BigQuery · AWS · MotherDuck |
One file governs the whole path — source, schema, quality, PII, lineage, transformation, materialization, SLOs. The contract is the invariant; the framework and backend are pluggable. Read the docs →
Our philosophy:
→ simple by design — plain YAML + SQL, nothing new to learn
→ executable, not just descriptive
→ SQL-native, not framework-specific
→ intent in the contract, engine as a flag
→ one artifact, readable by humans and agents
→ portable across every lakehouse — and every AI agent
→ the contract persists; the tool, model, and platform are replaceable
The contract
version: 1.0.0
info: { title: Orders, domain: sales, system: orders, table_name: silver_orders, target_layer: silver }
# where it comes from — read the sales-domain bronze table incrementally (by ordered_at)
source: { type: table, path: "table:lakehouse.sales.bronze_orders", load_mode: incremental, watermark_field: ordered_at }
model:
fields:
- { name: order_id, type: integer, required: true }
- { name: customer_email, type: string, pii: true, masking: partial }
- { name: amount, type: float, required: true }
- { name: order_total, type: float } # derived below
- { name: ordered_at, type: timestamp, required: true }
primary_key: [order_id]
# one declared step between source and target
transformations:
- phase: pre
derive: { field: order_total, sql: "amount + shipping_fee" }
quality:
enforce_required: true # completeness: required fields present
row_rules:
- { name: positive_amount, sql: "amount > 0" } # correctness
dataset_rules:
- { name: order_id_unique, unique: order_id } # completeness: no duplicate keys
- null_ratio: { field: customer_email, max: 0.02, category: completeness } # threshold: ≤2% nulls
# freshness + volume the framework checks each run (delivery SLOs)
service_levels:
freshness: { threshold: "1h", field: ordered_at } # timeliness — measured against ordered_at
row_count: { min_rows: 1 } # volume
# where it lands — converge the silver Iceberg table in the sales domain
materialization: { strategy: merge, format: iceberg, location: "s3://lakehouse/sales/silver_orders" }
SQL-first, with business shorthands. Any rule can be raw sql: "…" (like positive_amount); the shorthands — unique, null_ratio, enforce_required — are readable wrappers that compile to the same SQL. Reach for whichever reads clearer; the framework runs SQL either way.
The whole path, one file — each block answers one question:
| Block | Answers |
|---|---|
source |
where the data comes from — the primary source (here, bronze); join more via links |
model · primary_key |
what it is — schema + keys |
transformations |
how it's shaped |
quality |
the rules it must pass — correctness + completeness (row rules, uniqueness, null-ratio thresholds) |
service_levels |
the delivery SLOs — freshness + volume (availability too) |
materialization |
where it lands (silver Iceberg) |
Multi-source is first-class: a contract reads one primary source and joins any number of additional sources via links — other tables, domains, or systems (e.g. enrich orders with a customers dim, or a fx_rates table for currency).
One framework reads this file and does the rest — ingest → transform → validate → quarantine → mask → materialize → check SLOs. No spec-vs-code drift.
See it in action
An AI agent proposes a contract; you review it; then data is materialized. Spec-driven development for the data plane — align before acting.
You: /olc:contract "daily revenue by city from Stripe charges, drop test rows, freshness < 6h"
AI: Created olc/changes/revenue-daily/
✓ proposal.md — source: payments.silver_stripe_charges; grain: (date, city)
✓ contract.olc.yaml — schema + quality + SLO + materialization: merge [schema-valid]
✓ tasks.md — wire source · add rules · set SLO · materialize
You: /olc:validate
AI: Schema OK. Dry-run on 5,000 sample rows:
4,812 kept · 188 quarantined (1.2% test rows, 2.5% negative fare) · freshness 3h ✓
You: /olc:apply --provider duckdb
AI: Materialized silver.revenue_daily (merge, DuckLake) — 4,812 rows.
Same contract runs unchanged on Spark/Delta, Snowflake, or BigQuery — just change --provider.
That dry-run needs no real data. /olc:validate generates synthetic rows from the contract's own schema, seeded with edge cases the gates should catch — so you prove the rules before wiring a live source:
| Injected edge case | Caught by |
|---|---|
test / staging rows |
the drop-test-rows rule |
negative fare |
positive_amount — correctness |
| nulls above 2% | null_ratio — completeness |
| duplicate keys | order_id_unique — completeness |
| stale timestamps | freshness SLO |
lakelogic generate synthesizes type-, range-, and rule-aware rows with a tunable invalid ratio; the agent reads the quarantine breakdown and self-corrects. Same dry-run, either way — greenfield (pure synthetic, zero data) or brownfield (a real sample from your source).
[!NOTE] The contract never named an engine —
--providerchose it at apply. The/olc:*verbs ship today for Claude Code and Codex (see below); the execute-against-real-data half comes from the reference framework.
Use it with your AI assistant
The workflow is portable across AI agents — same verbs, each assistant's native mechanism, no cloud required:
pip install -e . # the `olc` CLI (validate + init)
olc init --tools all --dry-run # preview every destination file
olc init --tools all # install; conflicts stop before any write
Eleven assistants ship today — Claude Code, Codex (ChatGPT), Gemini CLI, Cursor, GitHub Copilot, Windsurf, Cline, Amazon Q, Roo Code, Kilo Code, and the shared AGENTS.md standard (OpenCode, Zed, Jules, …) — each in its native format:
- Claude Code / Gemini CLI —
/olc:validate(schema check, works now) ·/olc:contract "<intent>"·/olc:review(breaking-change merge gate) ·/olc:discover·/olc:impact. - ChatGPT — the same verbs as Codex prompts, or a Custom GPT with the schema as knowledge for the web.
- Cursor / Copilot / Windsurf / Cline / Amazon Q / Roo / Kilo — the OLC rules load automatically for
*.olc.yaml.
Verbs are data-native — discover → contract → review → validate → impact — and the integration layer is open (no cloud). See skills/ and the Agent Workflow.
SQL-native
Know SQL? You already know OLC. Logic is SQL — not Python, not Spark code, not notebooks. The contract carries the SQL; the framework runs it unchanged on whichever engine you choose.
transformations:
- sql: |
SELECT o.*,
ROUND(o.quantity * o.unit_price * (1 - COALESCE(o.discount_pct, 0)), 2) AS line_total
FROM source o
phase: post
The shorthand ops (rename, filter, cast, join, rollup, …) are convenience wrappers that compile to SQL — each shows its SQL variant in the Transformation reference. SQL is the portability invariant; the framework rewrites dialect differences per engine (PySpark / duckdb / polars).
Why OLC
- SQL-native. Logic is SQL — readable by analysts and engineers, runs on any SQL engine. No translation layer.
- Executable, not just descriptive. The same file that documents the contract runs it — validation, quarantine, quality gates, PII masking, lineage, materialization. No spec-vs-implementation gap.
- Portable. One contract, every lakehouse. Same definitions on Spark / DuckDB / Polars → Delta / Iceberg / DuckLake, on Databricks / Snowflake / Fabric / BigQuery / AWS / MotherDuck.
- Broader than "data contract." The whole lakehouse surface — schema + quality + PII + lineage + materialization + SLOs — not just schema.
- Agent-native. Typed, self-validating, and executable — the ideal substrate for AI data agents to generate, self-correct, act, and reason across every platform.
Providers — one contract, every lakehouse
The providers matrix runs the same contract set across seven backends — each page shows the identical contract, its invocation, and what it materialized (honest ✅ Live / ◑ Static-validated). Like a Terraform provider registry: one contract, many backends.
| DuckDB/DuckLake | MotherDuck | Databricks | Snowflake | BigQuery | Fabric | AWS/Glue |
|---|---|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ | ◑ | ✅ |
Quickstart — validate a contract
The spec is a single JSON Schema; validate any OLC file against it in any language — no framework required. Keep *.olc.yaml contracts beside your SQL / dbt / PySpark and gate every PR on them:
pip install jsonschema pyyaml
python scripts/validate.py # discovers + validates **/*.olc.yaml
python tests/conformance.py # (this repo) the spec's own conformance corpus
A ready-to-use GitHub Action lives in .github/workflows/validate-olc.yml — drop it into any repo (point --schema at the published schema URL) and contracts are checked on every push.
To run a contract, use the reference framework:
pip install lakelogic
from lakelogic import DataProcessor
proc = DataProcessor("orders.olc.yaml", engine="duckdb") # or "spark" / "polars"
good, bad = proc.run(source_df) # validate + quarantine
proc.materialize(good, bad) # write per `materialization`
Specification, schema, and reference implementation
OLC is deliberately three separable layers, so the standard never collapses into one vendor's code:
Open Lakehouse Contract · the specification — what the fields MEAN
│
┌───────────┴───────────┐
▼ ▼
JSON Schema Pydantic reference models
structural executable behaviour, in the
validation, reference framework (LakeLogic)
any language
- Specification — defines what
model,quality,primary_key,materialization,pii,service_levels… mean. Language- and framework-neutral; documented in the field reference. - JSON Schema (
schema/open-lakehouse-contract.schema.json) — the machine-readable structural form. Validate an OLC file in any language. - Reference implementation — LakeLogic's Pydantic models + Core, which execute the intent. The JSON Schema is generated from these models, so it can't drift from a working framework.
The strict Pydantic model (olc/models/) is the canonical source the schema is generated from — and it lives in this public repo, so anyone can regenerate the open schema with no private dependency. The model is a reference shape, not the spec itself — any framework, in any language, may implement the same spec. Regenerate when the model changes:
pip install -e .[models] # pulls pydantic; the CLI itself stays jsonschema-only
python scripts/generate_schema.py # schema/ ← generated from the strict OLCContractV1 model
Complements ODCS
OLC complements ODCS, it doesn't compete. ODCS is the standard for the business + semantic agreement; OLC adds the engineering + execution contract that executes it.
| ODCS | Open Lakehouse Contract | |
|---|---|---|
| Ownership · stakeholders · business semantics | ✅ defines | reference / integrate |
| Schema · terms · SLA · quality expectations | ✅ defines | ✅ enforces at runtime |
| PII classification | ✅ classifies | ✅ masks at runtime |
| SQL rules | some representation | core design principle |
| Materialization (merge/append, Delta/Iceberg/DuckLake) | — | ✅ |
| Engine execution (Spark/DuckDB/Polars) · cross-engine portability | not its role | ✅ core objective |
ODCS standardises the agreement · OLC standardises the execution · the LakeLogic reference framework runs both. It imports and exports ODCS losslessly — import ODCS → run as OLC → export ODCS. See OLC & ODCS.
Part of a spec-driven movement
Spec-driven development for the data plane: humans and AI agree on a precise, machine-checkable contract, then agents generate, validate, and execute it — the same conviction behind OpenSpec (for AI coding) and ODCS (descriptive data contracts). See Agent-Native · Agent Workflow.
What's in this repo
| Path | What |
|---|---|
schema/open-lakehouse-contract.schema.json |
The spec: JSON Schema (Draft 2020-12), the language-neutral source of truth. |
olc/ |
The olc CLI — olc validate (schema-only, no framework) + olc init (install agent integrations). |
skills/ |
Agent integrations — for Claude Code, Codex, Cursor, GitHub Copilot, Gemini, Windsurf, and Cline (installed by olc init). |
examples/ |
Illustrative contracts. |
tests/ |
Structural conformance — JSON-Schema fixtures: valid/ must pass, invalid/ must fail. |
conformance/ |
Executable conformance — behavioural cases (contract + input → expected accepted/quarantined/materialised) run through DuckDB & Polars adapters to prove one contract behaves identically across engines. |
scripts/ |
validate.py (zero-install CI validator) + generate_schema.py (regenerate the schema from the reference model). |
docs/ |
The full documentation site (mkdocs-material) — concepts, providers, and a complete field reference. |
Documentation
pip install -r docs-requirements.txt
mkdocs serve # http://127.0.0.1:8011
Concepts (what/why/agent-native/agent-workflow/ODCS) · Providers matrix · a complete field reference covering ingestion, lifecycle, quality, security, transformation, materialization, lineage, SLOs, notifications, and extraction.
Status
Draft v1. Schema generated from the reference implementation — 28 top-level fields (schema, quality, materialization, lineage, PII/masking, SLOs, sources/links, environments…). Governance, formal versioning, and a language-neutral corpus are on the roadmap — contributions welcome.
License
Apache License 2.0. The Open Lakehouse Contract is an open specification — free to implement, extend, and build on.
Reference implementation: LakeLogic. This repo is the open specification — intentionally vendor-neutral.
Release files for open-lakehouse-contract 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| open_lakehouse_contract-0.3.1.tar.gz | 63.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| open_lakehouse_contract-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 133.8 kB
Release files / open_lakehouse_contract-0.3.1.tar.gz
| Download URL | open_lakehouse_contract-0.3.1.tar.gz |
|---|---|
| Size | 63.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c932b8f7cbdc2a44fa51c6e4d3d47deae4564a5677aa1429e4c83cc8fdf15ed
|
|
BLAKE2b-256 checksum How to use checksums |
3235bd1598ca3d8652395985c71c7f043afd5dc5047d730d36527991eb0e1703
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / open_lakehouse_contract-0.3.1-py3-none-any.whl
| Download URL | open_lakehouse_contract-0.3.1-py3-none-any.whl |
|---|---|
| Size | 69.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8206e7cb4a433aa7099e915199b4edec3e75da649366f47628346061c4180bb4
|
|
BLAKE2b-256 checksum How to use checksums |
6b4c8c4e94b0961e7b5065ba009b57d5ecede5b1a72ea62bca176b510a502c76
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|