Metadata-Version: 2.5
Name: reble
Version: 0.2.0
Summary: Git-style branching for Iceberg data warehouses: scoped branches, row-level diffs, fast-forward promotion.
Author: Reble contributors
License: Apache-2.0
License-File: LICENSE
Keywords: branching,data-engineering,dbt,iceberg,lakehouse
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Database
Requires-Python: >=3.10
Requires-Dist: duckdb>=1.0
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.7
Requires-Dist: pyiceberg[pyarrow,sql-sqlite]>=0.8
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: sqlglot>=25.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp>=2.1; extra == 'mcp'
Description-Content-Type: text/markdown

# Reble

[![CI](https://github.com/satya1395/reble/actions/workflows/ci.yml/badge.svg)](https://github.com/satya1395/reble/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/reble)](https://pypi.org/project/reble/)
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)

**The workspace where humans and AI agents change the lakehouse safely.**
Every change runs on an isolated Iceberg branch and is accepted only after
its consequences are visible.

- **For humans:** the branch button for the lakehouse.
- **For agents:** a transactional data-change API — scope, pin, run, diff,
  promote or discard.

The headline capability is **accept-with-consequences**: before you accept a
change, Reble shows you the exact rows it adds, removes, and modifies. A code
IDE can't do that; a lakehouse can, structurally — the branch already
materialized the effect.

```mermaid
flowchart LR
    M[("main<br/>(Iceberg tables)")]
    E["edited SQL"] -->|"scope: AST-changed ∪<br/>downstream closure"| RUN["reble run"]
    M -->|"upstream inputs pinned<br/>via Iceberg tags"| RUN
    RUN -->|"zero-copy branch refs"| B[("data branch")]
    B --> D["reble diff<br/>rows + schema"]
    D --> P{"reble promote"}
    P -->|"pinned bases still<br/>equal main"| FF["fast-forward main"]
    P -->|"drift"| RR["scoped re-run +<br/>fresh promote-time diff"]
    RR --> FF
```

## Quick start

```
pip install reble
reble init                # writes reble.yml; probes your catalog
git switch -c fix-orders  # or: --change-set agent-42 — git is one adapter
# ...edit two models...
reble run                 # → data branch: edited models + downstream closure
                          #   written; upstream inputs pinned via Iceberg tags
reble diff                # schema + row-level diff vs. branch base
reble status              # un-run edits, drifted pins, branch age/expiry
reble promote             # fast-forward if base is current; forced re-run with
                          #   fresh diff if main moved. No merge. Ever.
```

Bots and agents are first-class users: every command speaks a stable
[`--json` envelope](SPEC.md) with documented exit codes, and `run`/`diff`
stream versioned [`--events`](SPEC.md#event-streams) (NDJSON) for progress.
Change-sets don't need git: `reble run --change-set <id>` (or
`REBLE_CHANGE_SET`) keys the work; `--branch` resumes an existing data
branch under a new change-set.

## Models are plain SQL

No orchestrator required. `models/**/*.sql` — one file is one model, the file
stem is the model name, and a minimal header comment block carries the
semantics:

```sql
-- model: mart_orders      (optional; defaults to file name)
-- kind: table | view | incremental
-- key: order_id           (diff key; required for incremental)
select ... from stg_orders join raw_customers using (customer_id)
```

Lineage is parsed with SQLGlot: a table reference that matches another model
is an edge; anything else is an upstream input, pinned with an Iceberg tag at
run time. Cosmetic edits (whitespace, comments, casing) hash identically on
the canonical AST and never trigger a run. Every branch snapshot carries
provenance (`reble.model`, `reble.ast_hash`, `reble.run_id`) in its summary —
"which code produced this table state" is answered from the catalog itself.

## How it works

Reble is built on **native Iceberg branch refs** — a per-table Iceberg spec
feature supported by any catalog (Glue, Polaris, Nessie, Hive, or any
REST-compliant catalog). It is *not* a catalog and requires no new
infrastructure. A branch ref is metadata-only: zero bytes are copied.

- **Scoped branching** — scope = edited models ∪ downstream closure, capped
  by `--depth`.
- **Pinned inputs** — upstream tables pinned with Iceberg **tags**
  (`reble_pin__*`) at run time; tags block `expire_snapshots`, so branch
  reads stay correct even while main moves.
- **Row-level diffs** — computed on your compute via DuckDB.
- **Promote semantics** — fast-forward only when every pinned base still
  equals current main; otherwise a scoped re-run and a fresh, promote-time
  diff. The PR diff is advisory; the promote diff is authoritative.

## Agents (MCP)

Any MCP host can drive the same verbs — the agent has no special powers:

```json
{
  "mcpServers": {
    "reble": {
      "command": "reble-mcp",
      "env": { "REBLE_PROJECT_DIR": "/path/to/project" }
    }
  }
}
```

Install with `pip install 'reble[mcp]'`. `reble_run` generates and returns a
change-set id; errors carry the spec exit codes as structured `error.code`
(3 = drift, 4 = promote-blocked). Tool docstrings are the agent-facing spec.

## Documentation

- [`SPEC.md`](SPEC.md) — normative CLI specification (v0.2): invariants,
  on-disk layout, `reble.yml` schema, command reference, JSON envelope,
  event streams, provenance, exit codes.
- [`DECISIONS.md`](DECISIONS.md) — recorded behavior decisions.

## Requirements

- Python 3.10+
- An Iceberg catalog (Glue, Polaris, Nessie, Hive, or any REST-compliant one)
- SQL models under `models/` (path configurable via `lineage.models_path`)

## Status

v0.1 — the full branch → run → diff → promote loop on DuckDB + pyiceberg,
with change-set keying, event streams, catalog-side provenance, and the MCP
tool surface for agents. Next: the DuckDB read path at scale
(`iceberg_scan` + spill) and the Spark runner.

## License

Apache-2.0.
