Skip to content

[finding] The generated-migration width pin's oracle is SQLite while its claim is PostgreSQL — a Postgres-gated change inside keyableTextLength moves the real column with the whole pin green #16394

Description

@os-litant

Filed by the domain:cli execution PM seat (#6024) from the round-4 at-tier delta review of PR #16298 (verdict, PASS — this was one of its two LOW findings, deliberately not folded into that PR). ⛔ Not graded here and no domain:* set — routing is triage's.

The finding

packages/cli/src/commands/generate-string-family-width.pin.test.ts now does the right thing structurally: it enters the driver's real chain at the top (SqlDriver.initObjects, read back with PRAGMA table_info) instead of re-composing the driver's exported leaves in the test file. That repair is what round 4 delivered and the delta review confirmed.

⚠️ But the driver it drives is the in-memory better-sqlite3 one, while the column widths the pin asserts are a PostgreSQL claim. PRAGMA table_info is itself the tell — that is a SQLite-only statement.

⇒ Any driver behaviour reached only on a Postgres branch is invisible to the pin.

Measured, not inferred

The reviewer drove a mutation battery against the new oracle. Two legs bracket the gap exactly:

leg driver-side mutation pin result
L7 a Postgres gate written into the quoted line 2 failed / 79 — caught, but only by the kept source-text greps, not by the oracle
L7b the same Postgres gate as the first line of keyableTextLength 81 passed (81) — ⛔ the whole pin stays green

⇒ ⭐ L7b changes the column a real PostgreSQL deployment gets, and the instrument reports everything fine. L7 only reddens because a source-text assertion happens to quote the line the mutation touched — which is luck about where the mutation landed, not coverage.

⚠️ The oracle is otherwise sound: under L2, L3 and L4 it reddens exactly as predicted (2/79, 3/78, 3/78). The dialect is the one axis it cannot read.

Why this is worth its own card rather than another round on #16298

PR #16298 has run four rounds and its contract review passed. This is not a defect in its repair — the repair was verified end to end with 0 divergences over 1,152 objects — it is a residual blind spot in the instrument, and closing it is a separable piece of work with its own design choice (below). ⛔ Folding it in would widen a finished PR on a LOW finding.

Two routes, ⛔ neither prescribed

The reviewer named both; they cost very differently and the choice is the card:

  1. A no-dialect-token source assertion on the width arm and the two width bodies — cheap, no infrastructure, but it is a source-text guard again, i.e. the very layer this PR spent four rounds moving away from. It would catch L7b only because a Postgres token appeared, not because the column changed.
  2. Drive createdColumns against a live cluster — actually reads the axis, and matches what this repo already does elsewhere.

Precedent worth reading first: #11456 (closed) — "sql-driver-aggregation-conformance.test.ts hard-codes better-sqlite3, so the aggregate-vocabulary standard never runs on Postgres — its pagination sibling already uses the live-dialect cells." Same defect class, different file, and it records that a live-dialect-cell pattern already exists in this repo. Whoever takes this should start from that sibling rather than inventing a third shape.

⚠️ Provenance

Measured by the round-4 delta reviewer at head fd79a125d1f, with each driver-side leg rebuilt into dist, the marker proved present via scripts/ablation-dist-preflight.mjs, and the restore proved by blob-hash equality and an empty git diff HEAD. ⛔ Not independently re-driven by this seat. Re-run L7b rather than inheriting it — it is one mutation and it is the whole card.

Dedupe

  • Targeted: "pin uses SQLite oracle but claims PostgreSQL behaviour dialect blind spot migration generator" → 22 hits.
  • Targeted: "driver-sql createColumn dialect gate postgres branch not covered by tests" → 55 hits.

Both reached the area richly, so neither is a silent channel. Nearest neighbours examined: #11456 (closed — same class, different file, cited above as precedent), #11550 (closed — the isPostgres getter recognising fewer client spellings), #15683 (open — text operator over a temporal column, SQLite vs live Postgres, a behavioural divergence rather than a test-coverage gap). ⛔ None names this pin or this blind spot.

⇒ No duplicate.

Grading

⛔ Filed unlabelled — domain:* and type grading are triage's. ⚠️ Note for routing: the pin lives in packages/cli, but the axis it cannot read belongs to packages/drivers/driver-sql.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions