Skip to content

feat: contract diffs + breaking-change gates (Bundle 7) - #11

Merged
iamgp merged 1 commit into
feat/shared-state-cachefrom
feat/contracts-breaking
Sep 15, 2026
Merged

iamgp merged 1 commit into
feat/shared-state-cachefrom
feat/contracts-breaking

Conversation

@iamgp

@iamgp iamgp commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Bundle 7 of the lakehouse-native stack, based on Bundle 6 (#10). Turns the opaque contract_hash change into a structured contract diff and gates promotion on breaking contract changes — computed live, so a stale artifact cannot hide them.

  • contracts.rs: contract_diff classifies every contract change SAFE / REVIEW / BREAKING — contract declared/dropped, enforcement on/off, column added/removed/renamed, type changes (numeric widening = review, incompatible = breaking), nullability tighten (review) / relax (safe).
  • Declared renames: [model.<name>.renames] new = "old" resolves a removed+added pair into a reviewable rename in both the contract diff and the physical schema diff. Stale or ambiguous declarations resolve nothing — they cannot mask a real removal or addition.
  • Persisted contracts: MaterializedRecord.contract -> contract_json in both SQLite and Postgres state (with migration), so candidate-vs-target comparisons run against what the environment actually recorded.
  • Branch diff: contract_changes section + lineage-aware impacts naming the downstream models/tests each breaking change hits.
  • Promotion: contract breaks join physical schema breaks in the schema gate, computed live from the workspace's desired contracts against the target's recorded contracts — editing a contract after diff cannot slip past on a stale artifact. --allow-breaking-schema waives both.
  • Plan/explain: contract-hash changes now name the affected columns and the breaking count instead of an opaque "contract or assertions changed".

Test plan

  • cargo test --workspace — all suites green
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • cargo fmt --all -- --check — clean
  • 11 unit tests in contracts.rs covering every classification + stale/ambiguous renames
  • diff.rs rename tests incl. stale-declaration edge cases
  • Engine integration: branch diff contract changes + impacts, declared rename, structured plan reasons
  • CLI: contract_breaking_changes gate incl. default-env folding

Stacked on #10 — do not merge independently.

@iamgp
iamgp force-pushed the feat/contracts-breaking branch 2 times, most recently from 4ffa819 to 311bee4 Compare September 14, 2026 08:59
@iamgp
iamgp force-pushed the feat/contracts-breaking branch from 311bee4 to d74ccbf Compare September 14, 2026 09:53
@iamgp
iamgp force-pushed the feat/contracts-breaking branch 2 times, most recently from dee5b27 to ff7d3e6 Compare September 14, 2026 12:19
@iamgp
iamgp force-pushed the feat/contracts-breaking branch from ff7d3e6 to be7820b Compare September 14, 2026 13:25
@iamgp
iamgp force-pushed the feat/contracts-breaking branch 2 times, most recently from d164888 to b304805 Compare September 14, 2026 15:49
…alysis, declared renames, persisted contracts

Bundle 7 on top of shared state/cache. Turns the opaque contract_hash
change into a structured, machine-readable contract diff and gates
promotion on breaking contract changes, computed live.

- contracts.rs: contract_diff classifies SAFE/REVIEW/BREAKING per
  change — contract added/dropped, enforcement on/off, column
  added/removed/renamed, type changes (numeric widening review,
  incompatible breaking), nullability tighten/relax.
- Declared renames: [model.<name>.renames] new = "old" resolves a
  removed+added pair into a reviewable rename in both contract and
  physical schema diffs. Stale or ambiguous declarations resolve
  nothing — they cannot hide a real removal or addition.
- MaterializedRecord persists the full contract (contract_json,
  SQLite + Postgres with migration), so base/target comparisons work
  against what the environment actually recorded.
- BranchDiffReport gains contract_changes and lineage-aware impacts
  naming the downstream models/tests a breaking change affects.
- Promotion: contract breaks join physical schema breaks in the schema
  gate, computed live against the target's recorded contracts — a
  contract edited after `diff` cannot slip past on a stale artifact.
  --allow-breaking-schema waives both.
- plan/explain reasons name the changed columns and breaking count
  instead of "contract or assertions changed".
@iamgp
iamgp force-pushed the feat/contracts-breaking branch from b304805 to 813d01f Compare September 14, 2026 16:26
@iamgp
iamgp added this pull request to stack #15 September 15, 2026 06:48
@iamgp
iamgp merged commit 7b7113c into main Sep 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant