You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 51dbc7b
Browse filesBrowse the repository at this point in the historyBrowse files
fix(migrate): a view recreated only around a table change is not drift (D3)
An adopter on 1.1.0-rc.2 rebuilt a SQLite database from the committed
migration chain. Every report and projection view's stored SQL was
byte-identical to the metadata's, yet `meta verify --db` and
`meta migrate --from-db` listed each view as `- view` / `+ view`, and
`verify` exited 1. Neither the text nor `--format json` said what differed.
The view comparison was not at fault. When a migration alters a table (a
column on every dialect; an FK or CHECK on SQLite/D1, which rebuild the
table, #243), Pass 2c drops and recreates every view that reads it. That
pair carried nothing that set it apart from a view whose definition
changed.
- migrate-ts: every view change carries a `reason` (ViewChangeReason:
missing | undeclared | definition | unfingerprinted | unchanged). A
recreate is `unchanged` only when equality is proven (the fingerprint on
Postgres, the normalized text on SQLite/D1). `isViewRecreateOnly` and
`withoutViewRecreates` are exported. computeDriftFromActual and
classifyDrift leave recreate-only views out. The emitted SQL is
unchanged.
- A text difference carries the first differing excerpt
(firstViewSqlDifference).
- Pass 2c keeps `unmanagedActual` from a superseded adoption, so an
unstamped Postgres view over an altered table needs --allow adopt-view
again (it bypassed the #239 gate before).
- cli: describeChange says why each view change was planned. The
committed-snapshot gate ignores recreate-only views. `verify --format
json` gains `schemaDrift` (changes[] with kind/object/detail, plus
findings[]). `migrate` (online, offline-snapshot and D1 paths) adds a
note naming the views that match, in text and in a `notes` array in
structured output.
- Tests: migrate-ts unit and drift tests; the CLI's verify-db-view-recreate
integration test; integration-tests lanes on a real SQLite (plus the D1
diff) and a real Postgres, both of which fail with the filter disabled.
- CHANGELOG (1.1.0 Fixed), docs/features/cli.md,
docs/features/migrations-and-drift.md.
Copy file name to clipboardExpand all lines: docs/features/migrations-and-drift.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ There are **7 drift sources**, and the toolchain has a guard for each.
13
13
|---|---|---|
14
14
|**Code-vs-DB**| Codegen — the generated SQL DDL is emitted from the same metadata as the entity / table code. | Build time |
15
15
|**Code-vs-API-doc**| Cross-port codegen from the same metadata. | Build time |
16
-
| **DB-vs-metadata** | `meta verify --db` (TS CLI) — introspects the live DB and fails if it has drifted from metadata. Includes modeled projection **view bodies** (a changed `CREATE VIEW` is `replace-view` drift); a hand-authored *unmodeled* view is unmanaged and never flagged. A schema concern owned by the Node toolchain regardless of server language; on the JVM ports the runtime auto-create/validator path was removed (ADR-0015) and the `metaobjects:verify` Maven goal is not available. Cloudflare D1 has no client wire protocol, so it can't go through `--db`'s Kysely-driver introspection — use `meta verify --dialect d1 [--d1 <binding>] [--remote]` instead (the same wrangler-shelled-out path `meta migrate --dialect d1` uses); `--remote` is required to check the *deployed* database, not the local `wrangler dev` shadow copy. Pointing `--db file:` at wrangler's local D1 state directory (`.wrangler/state/**/d1/**`) still runs, but only verifies that local copy — `verify` warns when it detects this. | CI on every PR |
16
+
| **DB-vs-metadata** | `meta verify --db` (TS CLI) — introspects the live DB and fails if it has drifted from metadata. Includes modeled projection **view bodies** (a changed `CREATE VIEW` is `replace-view` drift, reported with what differs: the first differing excerpt of the text on SQLite/D1, a fingerprint mismatch on Postgres). A view `meta migrate` drops and recreates only because the migration alters a table it reads, with its definition unchanged, is not drift and is not reported; a hand-authored *unmodeled* view is unmanaged and never flagged. A schema concern owned by the Node toolchain regardless of server language; on the JVM ports the runtime auto-create/validator path was removed (ADR-0015) and the `metaobjects:verify` Maven goal is not available. Cloudflare D1 has no client wire protocol, so it can't go through `--db`'s Kysely-driver introspection — use `meta verify --dialect d1 [--d1 <binding>] [--remote]` instead (the same wrangler-shelled-out path `meta migrate --dialect d1` uses); `--remote` is required to check the *deployed* database, not the local `wrangler dev` shadow copy. Pointing `--db file:` at wrangler's local D1 state directory (`.wrangler/state/**/d1/**`) still runs, but only verifies that local copy — `verify` warns when it detects this. | CI on every PR |
17
17
|**Migration-vs-metadata**| The Node `meta migrate` emits migrations FROM metadata diffs — they cannot drift from metadata by construction. Schema migrations for **every** port are owned by this Node toolchain (`@metaobjectsdev/cli migrate`, ADR-0015); the C# and Python migrate surfaces were removed. | Build time |
18
18
|**Generated-edited**|`@generated` headers in emitted code + three-way merge that preserves hand-edits inside non-generated regions. | Code review |
19
19
|**Prompt-vs-payload**| FR-004 `Renderer.verify` parses `{{...}}` references in templates and checks each one exists on the payload VO. | Build time + runtime |
`the schema gate's differences are in schemaDrift — changes[] (metadata vs database, one row per change) and findings[] (migration ledger and committed snapshot)`,
2026
+
);
2027
+
}
2028
+
if(drifted.some((g)=>g.gate!=="schema")){
1992
2029
help.push(
1993
2030
`the failing gate's drift DETAIL is printed as text on stderr — this payload carries the verdict only`,
1994
2031
);
@@ -2041,11 +2078,12 @@ function buildVerifyPayload(input: {
// The honest boundary. Everything named here is REACHABLE — it is printed as
2045
2083
// text on stderr — but it is not in this document, and a reader must not have
2046
2084
// to discover that by its absence.
2047
2085
notRepresented: [
2048
-
"per-gate drift detail (which template variable drifted, which schema change, which generated file differs, which migration failed to replay) — printed as text on stderr; this payload carries each gate's pass/fail verdict",
2086
+
"per-gate drift detail for every gate but schema (which template variable drifted, which generated file differs, which migration failed to replay) — printed as text on stderr; this payload carries each gate's pass/fail verdict, and the schema gate's differences in schemaDrift",
2049
2087
"the loader's own warnings and the agent-context/manifest advisories — printed as text on stderr",
0 commit comments