Fluid Forge Docs Baseline: CLI 0.12.0
Release Date: July 18, 2026 Status: Current stable docs baseline (supersedes 0.11.0)
Headline
0.12.0 is the dbt-integration + schema-GA release. Contract schema 0.7.5 is promoted to stable and becomes the default for untagged contracts — the vector/embeddings vectorConfig output port and the Redshift-Serverless/Kinesis binding fields are now GA, no opt-in pin required. On the dbt side, a full integration wave lands: a faithful brownfield importer (fluid import dbt reads target/manifest.json), dbt model contracts (--model-contracts), a MetricFlow bridge (semantic_models + metrics YAML from the contract's semantics block), auto-emitted packages.yml and sources.yml freshness blocks, run_results.json parsed into run records and verify checks, and dbt Fusion / dbt Core v2 engine detection with engine-aware tests:/data_tests: emission. fluid verify grows a second reconcile leg: --reconcile-lineage cross-checks declared lineage against local run evidence and the catalog publish payload.
pip install --upgrade data-product-forge.
Who should upgrade
Any team with an existing dbt project (the importer turns dbt parse output into a governed FLUID contract), anyone generating dbt projects from contracts (model contracts, MetricFlow semantics, packages/freshness emission, Fusion compatibility), and anyone building AI/RAG products — vectorConfig is now stable and default-available. Note the one-time digest churn for untagged contracts described under Compatibility.
What changed in v0.12.0
Schema — 0.7.5 promoted to stable (GA); 0.7.6 opens as preview
0.7.5is now the default schema version for untagged contracts (contracts that do not declarefluidVersion). Everything the0.7.5preview carried is GA:- the vector / embeddings
vectorConfigoutput port consumed byfluid generate vector(pgvector RAG target), - the Redshift Serverless + Kinesis
bindingLocationfields (stream,namespace,workgroup,iam_role_arn,external_schema,glue_database), - the streaming Kafka→Iceberg surface the version originally introduced.
- the vector / embeddings
0.7.6opens as the next preview — bundled and fully validatable when a contract explicitly declaresfluidVersion: "0.7.6", identical to0.7.5at open; additive preview fields will land there. Preview versions are never the silent default.- Contracts that explicitly pin a
fluidVersionare unaffected.
Added — fluid import dbt (brownfield dbt importer)
fluid import dbt <project-dir|manifest>converts a real dbt project'starget/manifest.json(produced bydbt parse— no warehouse access needed) into a FLUID contract. Stdlib-only JSON parse, no dbt-core dependency; one DataProduct per dbt project.- Faithful, not simplified: every model/seed/snapshot becomes an expose (no model cap), the
ref()-derived DAG is recorded per expose, dbt generic tests are recovered asdq.rules[](via the same shared test mapping the generators use —relationshipsand range tests become columnvalidationRules), sources becomeconsumes[]with freshness mapped toqosExpectations.freshnessMax, folder layout maps tometadata.layer+metadata.productType(staging→Bronze/SDP, marts→Gold/CDP), and acatalog.jsonoverlay supplies warehouse-accurate column types when present. - Requires manifest schema v9+ (dbt 1.5, 2023); the primary target is v12 (dbt 1.8+). Run
dbt parsefirst sotarget/manifest.jsonis fresh. - The legacy no-argument directory scan (
fluid import/fluid import --dir) now routes a dbt project with atarget/manifest.jsonto this importer automatically.
Added — dbt model contracts (--model-contracts)
fluid generate transformation --model-contractsemits a dbt model contract on every expose model:config: {contract: {enforced: true}}plus per-columndata_type(adapter-correct for bigquery/snowflake/redshift/duckdb) andconstraints(not_nullfor required columns,primary_keyfor declared keys), all derived fromexposes[].contract.schema[].dbt buildthen fails in producer CI whenever the model's output diverges from the contract — build-time enforcement of the contract-first pitch.- Opt-in (enforcement fails builds for already-drifted user SQL); requires dbt-core ≥ 1.5; dbt-only (ignored with a warning for other engines).
Added — MetricFlow bridge (semantic_models + metrics YAML)
- When a contract carries
exposes[*].semantics, the generated dbt project now includesmodels/semantic_models.ymlwithsemantic_models:+metrics:blocks (dbt Semantic Layer / MetricFlow shape). Simple, derived, and ratio metric types all map; a day-grainmetricflow_time_spinemodel is emitted alongside (MetricFlow hard-requires it). - Defaulting satisfies MetricFlow parse strictness: primary entity derived from the expose's key column,
defaults.agg_time_dimensionresolved or synthesized, unresolvable measures/metrics dropped with a warning rather than emitting a project that failsdbt parse. - Contracts without a semantics block are untouched — byte-identical output.
Added — packages.yml + sources.yml freshness emission
- Generated dbt projects whose tests reference
dbt_utils./dbt_expectations.now auto-emit apackages.ymlwith range-pinned entries for exactly the packages the emitted tests use, so the project passes its owndbt deps+dbt parsewithout hand-authoring. Under--mesh-hubthe pins fold into the emitteddependencies.ymlinstead (dbt forbids the two files coexisting); a user-managedpackages.ymlis never overwritten. - Contract freshness promises now reach
dbt source freshness:sources.ymlgains afreshness:block per source table, derived from upstreamexposes[].qos.freshnessSLO(→warn_after) and consumerconsumes[].qosExpectations.freshnessMax(→error_after), withloaded_at_fieldresolved from the upstream acquisition cursor field where possible. - Bug fixed in passing: emitted
dbt_utils.recencytests previously carried a non-dbt_fluid_windowargument that faileddbt compile; the window now maps to realdatepart/intervalvalues.
Added — run_results.json → run records + verify checks
fluid apply --mode amend-and-buildpreviously discarded everything dbt reported except the process exit code. The runner now parsestarget/run_results.json(versions v1–v6, stdlib only) and persists a canonical run record per dbt node, so failing contract tests surface influid runs statusand influid verify, which gains transformation-side checks (dbt_tests_passed,no_error_severity_failures) that gate the exit code under--strict.
Added — dbt Fusion / dbt Core v2 compatibility
- The dbt runner now detects the engine flavor (
fusionvscore+ version) fromdbt --version. Fusion compiles its adapters in and lists no plugins, which previously failed the adapter probe and silently punted every Fusion user to the slow Docker fallback — Fusion now runs natively.fluid doctorand the welcome scan report the detected engine flavor. - Engine-aware
tests:/data_tests:emission. dbt-core 1.8 renamed the data-test key, and Fusion strict-parses (the legacytests:fails). Generated projects now pick the right dialect automatically:--dbt-tests-key auto|tests|data_tests(env:FLUID_DBT_TESTS_KEY), whereauto(default) probes the dbt binary you would actually run — Fusion or core ≥ 1.8 getdata_tests:, core < 1.8 or no detectable binary gets the universally-parsed legacytests:. Pass an explicit value in CI generators with no local dbt binary. - The dbt executable resolves via
$DBT_EXECUTABLE(absolute path, bare name, or multi-token wrapper) before falling back toPATHand the active venv. See Environment Variables.
Added — fluid verify --reconcile-lineage
- A local-only cross-check that the contract's declared lineage (
consumes[]/exposes[]) agrees with the lineage that was actually observed (run records + cursor state under.fluid/) and the lineage that would actually be published (the catalog payload rebuilt locally — no network). Three drift classes:declared_but_never_read(soft) — a consume with no run evidence; never fails.read_but_undeclared(critical) — a stream a runner actually read that the contract never admits to; gates under--strict.publish_payload_mismatch(critical) — the registrar payload's lineage edges disagree with the contract; gates under--strict.
--warn-onlydowngrades drift from both reconcile legs (--reconcile-dbt/--reconcile-lineage) to warnings. Seefluid verify.
Fixed & internal
- Copilot enrichment now emits schema-valid slots + ISO-8601 dq-rule windows, closing a class of authoring-time validation failures.
- The three contract→dbt-test mappers are consolidated into one shared module (the importer's reverse mapping reads the same table, so import→generate round-trips stay symmetric).
- CI: the overloaded 3.12 test leg is split into a parallel coverage-and-audit job; a test-leg hang (timezone-formatter × warning-amplification) is retired; the release image's Docker CVE gate is green again via base-image upgrade + re-curated ignores.
Compatibility
- One-time plan/bundle digest churn for untagged contracts. Because untagged contracts now default to
0.7.5(previously0.7.4), their canonical form changes once, sobundleDigest/planDigestvalues recomputed after upgrade will differ from pre-0.12.0values. This is deliberate and happens once per contract on first re-plan after the upgrade. Re-runfluid bundle && fluid planto re-baseline; contracts that explicitly declarefluidVersionare unaffected. - Contract schema:
0.7.5is stable and the new default;0.7.6is bundled as opt-in preview. No fields were removed; validation of explicitly-pinned contracts is unchanged. - SDK / custom-scaffold: unchanged (
data-product-forge-sdk 0.10.0,data-product-forge-custom-scaffold 0.4.0). - Install:
pip install --upgrade data-product-forge→0.12.0.