← All Releases

v0.2.7

2026-06-13

INCREMENTALS REBORN & ADAPTER ISOLATION

Two foundations in one release. First: the dbt incremental experience, across engines — is_incremental() and {{ this }} now work in f_incremental models, your SQL owns the delta, and a tiny persisted index replaces full source replicas. Second: every dbt adapter now runs in its own isolated environment with its own dbt-core version — adapter version conflicts are structurally extinct. (0.2.6 was an internal milestone; all of its environment-isolation work ships here.)

ADDED

  • is_incremental() and {{ this }} are real in f_incremental models: the compat macros override dbt's check, and dvt run probes prior state locally before compiling — your Jinja delta logic (max-watermarks, NOT IN, anything) drives extraction.
  • The {{ this }} index: instead of replicating source tables, DVT keeps a pruned index of your model's own target (a NOT IN subquery stores ONE column, not the table), persisted between runs and self-maintained after every load — the target is read once, ever.
  • Two-phase delta pushdown: scalar watermarks (MAX(...) FROM {{ this }}) evaluate locally and inline as literals into each source's extraction — true deltas leave the source, nothing else.
  • Homogeneous jinja incrementals take the Sling direct path: the engine evaluates its own NOT IN subquery natively, single hop.
  • Sling direct path for watermark-style f_incremental models (target-side watermark, delta-only streaming).
  • ADAPTER ISOLATION — one dbt-core per adapter: your environment carries only the default target's dbt adapter; every other adapter lives in its own buried environment under .dvt/ running whatever dbt-core version IT wants. Verified live: dbt-mysql on dbt-core 1.7.19 working beside a master environment on 1.11 — a pairing that is impossible in any single environment. Lagging community adapters can lag in peace.
  • uv becomes the one prerequisite — and dvt sync installs it for you when missing, so you never have to know what it is. Environment names are deliberately opaque; a registry maps adapters to environments and DVT picks the right dbt binary per invocation (dvt run --target, dvt debug --all, everything).
  • dvt sync is a full reconciler: switch the default target and the master environment swaps adapters, dbt-core re-resolves for the new default alone, the new default's buried environment is pruned, and the old default's adapter gets buried instead — one command, full reshuffle. Adapters that cannot coexist with dvt-core at all run isolated even as the default.
  • dvt clean removes all isolated environments (and tmp staging) in one stroke; dvt sync rebuilds them on demand. Tight grip, zero residue.

CHANGED

  • Source replicas retired for jinja incrementals — the cache holds indexes, not datasets. Legacy watermark_column models keep their proven path.
  • dvt clean is about project assets, never data: it removes the isolated environments and tmp staging; the incremental cache is owned solely by dvt run/build --full-refresh (selective via --select).
  • jinja-incremental deltas apply via Sling upsert and require a unique_key — a silent full-refresh fallback could wipe the target, so it is refused with guidance.
  • insert_overwrite and microbatch strategies are refused loudly (no honest Sling equivalent).
  • The dvt version banner now draws the real DVT mark — the triangle inside the circle.

FIXED

  • Parallel-wave DDL race on the index-signature table.
  • Legacy adapter wheels shipping overlapping files no longer corrupt the shared dbt stack on reconciliation (forced reinstall repairs in the same breath).

Get it: pip install dvt-core==0.2.7 · wheels on PyPI for macOS (arm64 + x86_64) and Linux, Python 3.10–3.12.