Repository navigation
[finding] The driver-conformance census cannot see the dialect axis — a suite running on 1 of 3 dialects scores identically to one running on all 3 #12014
Description
Activity
yinlianghui-tw commented
on Aug 25, 2026 CollaboratorMore actionsTriage:
finding→pm:queue+domain:engine, Task, M — this is restoration of a ruled axis, not a new convention decision: ADR-0053 D-A3 already declares the matrix asdriver × {SQLite, Postgres at minimum}, and today that declared axis is enforced by nothing the census can see, which is exactly how #11456 sat green while PG threw 42883. Scope: givecheck:driver-conformancethe dialect axis, with the deliberate-vs-accidental distinction carried by an explicit marker — the existingdialectCell('sqlite')call is the candidate the card names (7 files already use it); an unmarked hard-coded client in a conformance-named suite becomes a named finding. First measurement of the 99-literal population lands as a one-act baseline in the #5480$commentdiscipline (not newly written looseness, not a raised ratchet), maintainer-vetoable at review. ⛔ Do not reclassify the 99 by guesswork — the gate only needs to force the marking, not to decide each file's intent for it.
Generated by Claude Code
Claim: PM loop (
domain:engineseat)
Session:session_01W6HFzyH98W1YaQXhJUJt6o
Branch:claude/issue-12014-conformance-census-dialect-axis
Worktree:objectstack-issue-12014
Domain:domain:engine
Container & model: M,mode:subagent,model: opus
Clause-②: no — a census/gate script plus a convention marker. No public surface widens and no accept/reject door on a shipped contract moves.⚠️ Re-measured at claim, and the numbers have moved — in the direction that strengthens the cardThe card measured
packages/drivers/driver-sql/srca day ago. Measured again just now onorigin/main:card now delta files with a literal client: 'better-sqlite3'99 105 +6 files routing through live-dialect-matrix40 44 +4 files using dialectCell(7 7 0 ⇒ the invisible population grows with ordinary work while the marker that would make it visible stays flat. This is not a static debt to pay down once; it accretes, which is the argument for closing it at the census rather than by sweeping files.
Serial constraints cleared
Primary surface
scripts/check-driver-conformance.mjsandpackages/drivers/driver-sql/src/live-dialect-matrix.testkit.ts— no open PR touches either (checked across all open PRs).⛔ Two test files are held by in-flight work and must not be edited:
sql-driver-11224-update-stamp-precision.test.ts— [finding]sql-driver-11224-update-stamp-precision§3 is a probabilistic guard that reds with CORRECT code on a fast runner — and its failure is byte-identical to the defect it guards against #11572 / PR test(driver-sql): make the update-stamp precision guard deterministic — drive §3's clock instead of racing it #12112, enqueued.sql-driver-11794-richtext-text-family.test.ts—signature/qrcodehave nomaxLengthenforcement anywhere, so they cannot join the TEXT family — a data-URI signature is refused at 255 chars and the declared bound binds nothing #11875 / PR feat(data): signature and qrcode join the bounded-string family end to end #12119, in flight.
⛔
sql-driver.tsbands8600–9200(#12015),10100–10560(#11722) and13275–13900(#11875) are all held. This card should need none of them.What is ruled and what is yours
Triage queued this without prescribing a fix, and the card is explicit that closing it "means deciding what marks a deliberate single-cell suite … a convention decision, not a mechanical edit".
dialectCell('sqlite')already exists for exactly that purpose and 7 files use it alongside the literal, so the marker is not hypothetical.⛔ The 105 are not 105 defects and must never be reported as such —
sql-driver-11321-sqlite-audit-default-canonical.test.tsis about SQLite by name. The gap is that "deliberately single-dialect" and "accidentally single-dialect" are spelled identically today.Bounded shape: give the census a dialect axis so the number becomes visible and honest, with
dialectCell()as the marker of deliberateness. Report the classification counts; do not reclassify all 105 files — that is a sweep, and it is a separate card whose size this one's number should decide.The instance that proves the cost is measured and in-repo: #11456 sat green on
mainand on every PR while, on live PG 16.13,sum/avg/min/maxover a boolean column threw SQLSTATE42883.
Generated by Claude Code
{ "issue": 12014, "status": "done", "branch": "claude/issue-12014-conformance-census-dialect-axis", "pr": "https://github.com/objectstack-ai/objectstack/pull/12134", "premise_still_valid": true, "summary": "Added a DIALECTED invariant to scripts/check-driver-conformance.mjs, giving the census the third axis ADR-0053 D-A3 declares. A conformance suite in a dialect-capable driver must now SAY which dialects it runs on: it passes by naming a stance symbol imported from its driver's dialect-matrix testkit (DIALECT_CELLS/LIVE_DIALECT_CELLS = matrix; dialectCell/PG_CELL/MYSQL_CELL/declareDialectCell = named cells), and the population is defined by the presence of that DECLARATION rather than the absence of a client literal, so moving the config into a helper cannot respell a suite out of reach. Dialect-capable drivers and their cell ids are discovered from disk via the DIALECT_CELLS export, never hardcoded; the other four drivers have no such testkit and are reported as single-backend counts rather than skipped silently. Scoring is per FILE, not per cell, because FILTER_TEXT_CASES on this tree is covered by both a matrix suite and an undeclared one and per-cell scoring would let the latter hide. I re-measured the population on origin/main at e7480a8067 and got exactly the PM's numbers: 105 literal client:'better-sqlite3' files, 44 live-dialect-matrix routers, 7 dialectCell users. The 105 are NOT 105 defects and the gate does not treat them as any -- it scores only the 7 test files that make a cell of this census covered (5 matrix, 2 undeclared), plus 1 non-test covering file named in the output. Per cell, 8 of 9 dialect-scored cells have a matrix-routed suite; the exception is FILTER_COMPARAND_TYPE_CASES, whose own CASE_SETS entry says the accepted types 'compile everywhere' while it is measured on one dialect. The 2 undeclared suites are seeded into a new DIALECT_LEDGER as a one-act measured baseline rather than marked, because marking them would record a claim about intent I cannot verify -- and no test file is edited, so the branch stays inside the declared file surface. The second ledger carries the same MAINTAINER-ONLY authority label as the first under the #8435 convention. Mid-branch I replaced my own hand-rolled stripComments with scripts/js-comment-mask.mjs, the repo's single answer to 'comment or code'; the census output is byte-identical across that swap, so it is a change of provenance and not of measurement.", "tests": "Gate union DERIVED, not recalled: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (no paths; it takes the changeset itself) -> 8 families, all run at bc203848df, the final commit. Exit codes captured before any pipe (`cmd > log 2>&1; EXIT=$?`), and every verdict quoted below is the gate's own printed line, never $?. check:driver-conformance 'OK - 45 covered cell(s), 0 in the DEBT ledger, 0 exempt.' plus the new 'dialect axis - 7 conformance suite(s) across 1 dialect-capable driver(s): 5 run the matrix, 0 declare named cell(s), 2 in the DIALECT ledger. 8 of 9 dialect-scored cell(s) have a matrix-routed suite. 36 covered cell(s) belong to 4 single-backend driver(s)'; self-test 'OK self-test: ... And it holds the DIALECT axis (#12014)'. check:agent-test-spelling '0 violations - 374 file(s)'. check:cross-package-test-inputs and check-cross-package-test-inputs 'OK: 16 package(s) read outside themselves, all declared'. check:entry-guard '161 scripts/ file(s) - every entry guard goes through invoked-as.mjs'. check:parse-guard '160 scripts/ file(s) - every TypeScript parse goes through ts-parse.mjs.'. check:pnpm-filter-targets '135/170 --filter occurrence(s) ... resolve'. check-ci-filter-parity 'OK: all 96 declared cross-package glob(s) (81 unique) are covered'. check:nul-bytes 'OK (scanned 6728 text file(s) ... no raw ASCII control bytes).' Three families dispatch-gates flagged as artifact rosters co-located with scripts/, where it says a 'silent' verdict is not evidence in EITHER direction, were RUN rather than reasoned about: check:i18n-stale-fill, check:pm-dispatch-gates ('580 cases pass'), check:partof-closing-keyword ('28 cases pass') -- all green. Because the branch now depends on the shared comment mask I also ran its two owning gates: js-comment-mask --self-test ('35 cases pass') and check-comment-mask-corpus ('5098 files, 0 disagree, 0 unparseable'). eslint --no-inline-config on the one changed file: 1 file, 0 errors, 0 warnings. ABLATION (direction predicted in writing BEFORE the run: new gate red with exactly one DIALECTED error naming the file, covered-cell count still 45, baseline gate still green). Mutation: in sql-driver-aggregation-conformance.test.ts the import specifier './live-dialect-matrix.testkit.js' -> './ablated-not-the-testkit.js', reproducing the pre-#11456 state at the level the census reads. NO REBUILD APPLIES and none is claimed: the subject is a .mjs gate script read as text with no dist/ artifact between the edit and the measurement, so the build-then-measure clause has no referent here -- what does apply is the on-disk proof, which was done BEFORE any result was read, by anchored grep counts of the exact text changed: removed text present 0, injected text present 1 (not git diff --stat, not an editor exit code). Results: baseline census (origin/main) exit 0 '45 covered cell(s)' on BOTH the clean and mutated trees -- `diff` of the two runs is EMPTY, which is the #12014 defect reproduced rather than argued; new gate exit 1, 'DIALECTED errors: 1 total errors: 1', naming sql-driver-aggregation-conformance.test.ts. Restore VERIFIED, not trusted: trap ... EXIT INT TERM, `git checkout HEAD -- \"$TARGET\"` with an absolute path, then git hash-object of the working file e488edad7ae0994c9a5a3ed5ff7b890d1ef9087c == git rev-parse HEAD:(the same path), and git status --porcelain empty; gate green again after restore. The ablation was re-run from scratch after the comment-mask swap, because the detector changed. The same red/green is permanent in --self-test, driven over a synthetic tree by the real dialectAudit (parameterised for that, as discoverDrivers already is) rather than a re-implementation: undeclared suite RED / declared GREEN over the same tree, ledger reconciliation in all three directions, stance classification in all three directions including the declareDialectCell-is-one-cell precedence, and a non-vacuity guard that fails loudly if the prose-only fixture ever stops being recognisable as a stance in RAW text (without which the comment-mask assertion would pass vacuously forever).", "open_questions": [ { "question": "The two seeded DIALECT_LEDGER rows are a measured baseline, not a resolution. Should each suite be converted to the dialect matrix, or marked as a deliberate single cell? I deliberately did not decide: marking records a claim about intent that cannot be verified from outside, and the card forbids reclassifying by guesswork.", "options": [ "A - convert sql-driver-comparand-type-conformance.test.ts to the matrix and mark sql-driver-icontains-and-retired-operators.test.ts dialectCell('sqlite'). The comparand-type cell is the only dialect-scored cell with NO matrix-routed suite and its case-set says the accepted types 'compile everywhere'; the icontains cell is already matrix-covered by sql-driver-text-case-conformance.test.ts, so a second sqlite-only suite over it is plausibly deliberate.", "B - convert both to the matrix. FILTER_TEXT_CASES is the case-set whose answer is KNOWN to diverge by dialect (#6518: GLOB on SQLite, LIKE on Postgres, LIKE over CAST(.. AS BINARY) on MySQL), so a sqlite-only suite over it is the shape most likely to be accidental.", "C - mark both dialectCell('sqlite') and keep the ledger empty. Cheapest, and defensible only if both really are deliberate -- which is exactly what is not established." ], "recommendation": "A, as a follow-up card rather than here. The comparand-type cell is the one with a measured gap (no multi-dialect cover at all, against a case-set that claims 'everywhere'), so it earns the conversion; icontains is a second suite over an already-matrix-covered cell, so marking it costs nothing real. B is defensible too and I would not argue against it -- the maintainer's call. Either way it is a change to what a SUITE asserts, which is outside this card's Clause-2-no boundary, and the card's own instruction is that this card's number should size that follow-up. The number is 2." }, { "question": "Should 'every dialect-scored cell has at least one matrix-routed suite' be promoted from a printed measurement to an invariant? ADR-0053 D-A3 says 'Postgres at minimum', which the current gate reports but does not enforce.", "options": [ "A - promote it now. It is the invariant that most directly encodes D-A3.", "B - leave it as a printed measurement until the two ledgered suites are resolved. Promoting it today makes exactly one cell red (FILTER_COMPARAND_TYPE_CASES), and clearing that red means converting a suite -- outside this card's declared surface." ], "recommendation": "B for this card, and it is written into the script header as the named follow-up rather than left implicit. Promoting it here would have forced a test-file edit to land a gate change, which is the coupling the card's scope explicitly rules out. Once the question above is settled the population is zero and the promotion is free." } ], "out_of_scope_findings": [ "filed as #12135: check-driver-conformance's consumes() counts a comment-only mention as coverage -- its import-detection regex uses unbounded [\\s\\S]*? on both sides, so packages/drivers/driver-sql/src/sql-driver.ts (the driver implementation, not a suite) is scored as covering FILTER_LOGIC_CASES on the strength of two prose mentions at lines 28 and 3233. Changes no verdict today, but the wrong reason is sufficient on its own: delete a driver's only suite while leaving a comment naming the marker and the cell stays green. Not fixed in this PR because the remedy changes what CONSUMED counts, a different blast radius from adding an axis. Dedup note carried on the issue: the REST list endpoint returned HTTP 403 (known per-session outage), so the empty search is NOT claimed as evidence of no duplicate." ] }
Generated by Claude Code
os-dev-report
⚠️ Marker fallback, read this first: the previous comment (#issuecomment-5409125638) carried the report with the usual HTML-comment marker as its first line, and the GitHub body sanitizer ate it — read back, that comment's stored body begins with a bare newline, so it is invisible to a marker scan. This comment is the scannable copy, with the marker as literal text. The JSON below is byte-identical to the one in that comment; there is one report, not two. No comment-edit path was available to repair the original in place (the REST endpoint returns HTTP 403 in this session, the known per-session outage).{ "issue": 12014, "status": "done", "branch": "claude/issue-12014-conformance-census-dialect-axis", "pr": "https://github.com/objectstack-ai/objectstack/pull/12134", "premise_still_valid": true, "summary": "Added a DIALECTED invariant to scripts/check-driver-conformance.mjs, giving the census the third axis ADR-0053 D-A3 declares. A conformance suite in a dialect-capable driver must now SAY which dialects it runs on: it passes by naming a stance symbol imported from its driver's dialect-matrix testkit (DIALECT_CELLS/LIVE_DIALECT_CELLS = matrix; dialectCell/PG_CELL/MYSQL_CELL/declareDialectCell = named cells), and the population is defined by the presence of that DECLARATION rather than the absence of a client literal, so moving the config into a helper cannot respell a suite out of reach. Dialect-capable drivers and their cell ids are discovered from disk via the DIALECT_CELLS export, never hardcoded; the other four drivers have no such testkit and are reported as single-backend counts rather than skipped silently. Scoring is per FILE, not per cell, because FILTER_TEXT_CASES on this tree is covered by both a matrix suite and an undeclared one and per-cell scoring would let the latter hide. I re-measured the population on origin/main at e7480a8067 and got exactly the PM's numbers: 105 literal client:'better-sqlite3' files, 44 live-dialect-matrix routers, 7 dialectCell users. The 105 are NOT 105 defects and the gate does not treat them as any -- it scores only the 7 test files that make a cell of this census covered (5 matrix, 2 undeclared), plus 1 non-test covering file named in the output. Per cell, 8 of 9 dialect-scored cells have a matrix-routed suite; the exception is FILTER_COMPARAND_TYPE_CASES, whose own CASE_SETS entry says the accepted types 'compile everywhere' while it is measured on one dialect. The 2 undeclared suites are seeded into a new DIALECT_LEDGER as a one-act measured baseline rather than marked, because marking them would record a claim about intent I cannot verify -- and no test file is edited, so the branch stays inside the declared file surface. The second ledger carries the same MAINTAINER-ONLY authority label as the first under the #8435 convention. Mid-branch I replaced my own hand-rolled stripComments with scripts/js-comment-mask.mjs, the repo's single answer to 'comment or code'; the census output is byte-identical across that swap, so it is a change of provenance and not of measurement.", "tests": "Gate union DERIVED, not recalled: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (no paths; it takes the changeset itself) -> 8 families, all run at bc203848df, the final commit. Exit codes captured before any pipe (`cmd > log 2>&1; EXIT=$?`), and every verdict quoted below is the gate's own printed line, never $?. check:driver-conformance 'OK - 45 covered cell(s), 0 in the DEBT ledger, 0 exempt.' plus the new 'dialect axis - 7 conformance suite(s) across 1 dialect-capable driver(s): 5 run the matrix, 0 declare named cell(s), 2 in the DIALECT ledger. 8 of 9 dialect-scored cell(s) have a matrix-routed suite. 36 covered cell(s) belong to 4 single-backend driver(s)'; self-test 'OK self-test: ... And it holds the DIALECT axis (#12014)'. check:agent-test-spelling '0 violations - 374 file(s)'. check:cross-package-test-inputs and check-cross-package-test-inputs 'OK: 16 package(s) read outside themselves, all declared'. check:entry-guard '161 scripts/ file(s) - every entry guard goes through invoked-as.mjs'. check:parse-guard '160 scripts/ file(s) - every TypeScript parse goes through ts-parse.mjs.'. check:pnpm-filter-targets '135/170 --filter occurrence(s) ... resolve'. check-ci-filter-parity 'OK: all 96 declared cross-package glob(s) (81 unique) are covered'. check:nul-bytes 'OK (scanned 6728 text file(s) ... no raw ASCII control bytes).' Three families dispatch-gates flagged as artifact rosters co-located with scripts/, where it says a 'silent' verdict is not evidence in EITHER direction, were RUN rather than reasoned about: check:i18n-stale-fill, check:pm-dispatch-gates ('580 cases pass'), check:partof-closing-keyword ('28 cases pass') -- all green. Because the branch now depends on the shared comment mask I also ran its two owning gates: js-comment-mask --self-test ('35 cases pass') and check-comment-mask-corpus ('5098 files, 0 disagree, 0 unparseable'). eslint --no-inline-config on the one changed file: 1 file, 0 errors, 0 warnings. ABLATION (direction predicted in writing BEFORE the run: new gate red with exactly one DIALECTED error naming the file, covered-cell count still 45, baseline gate still green). Mutation: in sql-driver-aggregation-conformance.test.ts the import specifier './live-dialect-matrix.testkit.js' -> './ablated-not-the-testkit.js', reproducing the pre-#11456 state at the level the census reads. NO REBUILD APPLIES and none is claimed: the subject is a .mjs gate script read as text with no dist/ artifact between the edit and the measurement, so the build-then-measure clause has no referent here -- what does apply is the on-disk proof, which was done BEFORE any result was read, by anchored grep counts of the exact text changed: removed text present 0, injected text present 1 (not git diff --stat, not an editor exit code). Results: baseline census (origin/main) exit 0 '45 covered cell(s)' on BOTH the clean and mutated trees -- `diff` of the two runs is EMPTY, which is the #12014 defect reproduced rather than argued; new gate exit 1, 'DIALECTED errors: 1 total errors: 1', naming sql-driver-aggregation-conformance.test.ts. Restore VERIFIED, not trusted: trap ... EXIT INT TERM, `git checkout HEAD -- \"$TARGET\"` with an absolute path, then git hash-object of the working file e488edad7ae0994c9a5a3ed5ff7b890d1ef9087c == git rev-parse HEAD:(the same path), and git status --porcelain empty; gate green again after restore. The ablation was re-run from scratch after the comment-mask swap, because the detector changed. The same red/green is permanent in --self-test, driven over a synthetic tree by the real dialectAudit (parameterised for that, as discoverDrivers already is) rather than a re-implementation: undeclared suite RED / declared GREEN over the same tree, ledger reconciliation in all three directions, stance classification in all three directions including the declareDialectCell-is-one-cell precedence, and a non-vacuity guard that fails loudly if the prose-only fixture ever stops being recognisable as a stance in RAW text (without which the comment-mask assertion would pass vacuously forever).", "open_questions": [ { "question": "The two seeded DIALECT_LEDGER rows are a measured baseline, not a resolution. Should each suite be converted to the dialect matrix, or marked as a deliberate single cell? I deliberately did not decide: marking records a claim about intent that cannot be verified from outside, and the card forbids reclassifying by guesswork.", "options": [ "A - convert sql-driver-comparand-type-conformance.test.ts to the matrix and mark sql-driver-icontains-and-retired-operators.test.ts dialectCell('sqlite'). The comparand-type cell is the only dialect-scored cell with NO matrix-routed suite and its case-set says the accepted types 'compile everywhere'; the icontains cell is already matrix-covered by sql-driver-text-case-conformance.test.ts, so a second sqlite-only suite over it is plausibly deliberate.", "B - convert both to the matrix. FILTER_TEXT_CASES is the case-set whose answer is KNOWN to diverge by dialect (#6518: GLOB on SQLite, LIKE on Postgres, LIKE over CAST(.. AS BINARY) on MySQL), so a sqlite-only suite over it is the shape most likely to be accidental.", "C - mark both dialectCell('sqlite') and keep the ledger empty. Cheapest, and defensible only if both really are deliberate -- which is exactly what is not established." ], "recommendation": "A, as a follow-up card rather than here. The comparand-type cell is the one with a measured gap (no multi-dialect cover at all, against a case-set that claims 'everywhere'), so it earns the conversion; icontains is a second suite over an already-matrix-covered cell, so marking it costs nothing real. B is defensible too and I would not argue against it -- the maintainer's call. Either way it is a change to what a SUITE asserts, which is outside this card's Clause-2-no boundary, and the card's own instruction is that this card's number should size that follow-up. The number is 2." }, { "question": "Should 'every dialect-scored cell has at least one matrix-routed suite' be promoted from a printed measurement to an invariant? ADR-0053 D-A3 says 'Postgres at minimum', which the current gate reports but does not enforce.", "options": [ "A - promote it now. It is the invariant that most directly encodes D-A3.", "B - leave it as a printed measurement until the two ledgered suites are resolved. Promoting it today makes exactly one cell red (FILTER_COMPARAND_TYPE_CASES), and clearing that red means converting a suite -- outside this card's declared surface." ], "recommendation": "B for this card, and it is written into the script header as the named follow-up rather than left implicit. Promoting it here would have forced a test-file edit to land a gate change, which is the coupling the card's scope explicitly rules out. Once the question above is settled the population is zero and the promotion is free." } ], "out_of_scope_findings": [ "filed as #12135: check-driver-conformance's consumes() counts a comment-only mention as coverage -- its import-detection regex uses unbounded [\\s\\S]*? on both sides, so packages/drivers/driver-sql/src/sql-driver.ts (the driver implementation, not a suite) is scored as covering FILTER_LOGIC_CASES on the strength of two prose mentions at lines 28 and 3233. Changes no verdict today, but the wrong reason is sufficient on its own: delete a driver's only suite while leaving a comment naming the marker and the cell stays green. Not fixed in this PR because the remedy changes what CONSUMED counts, a different blast radius from adding an axis. Dedup note carried on the issue: the REST list endpoint returned HTTP 403 (known per-session outage), so the empty search is NOT claimed as evidence of no duplicate." ] }
Generated by Claude Code
ACCEPT — PR #12134. And both open questions are answered below; neither needs the maintainer.
The ablation reproduces the defect instead of arguing it
This is the part that makes the card closable. The baseline census was run on the clean tree and on a tree where
sql-driver-aggregation-conformance.test.ts's testkit import was broken — reproducing the pre-#11456 state at the level the census reads:baseline census exit 0,
45 covered cell(s)on BOTH trees —diffof the two runs is EMPTYThat empty diff is #12014, demonstrated rather than described. The new gate then exits 1 with
DIALECTED errors: 1, naming the file. A gate card's ablation has to show the gate catching the thing the old one couldn't, on the same tree, and this does.The population design is better than what I sketched at dispatch
I framed the marker as
dialectCell(). The dev inverted it: the population is defined by the presence of a stance DECLARATION, not the absence of aclientliteral. That matters — under my framing, moving a driver config into a helper would respell a suite out of the gate's reach silently. Under this one it cannot.Scoring is per file, not per cell, with the reason stated:
FILTER_TEXT_CASESis covered by both a matrix suite and an undeclared one, and per-cell scoring would let the undeclared one hide behind its neighbour. That is the right call and it is the kind of thing that is only visible if you actually run the census.My fences held, and the 105 were not treated as defects
- One file changed —
scripts/check-driver-conformance.mjs. Zero*.test.tsedits, verified. That was the fence that mattered most, and it kept the PR minimal. - The gate scores 7 test files (5 matrix, 2 undeclared) plus 1 non-test covering file — not 105. ⛔ The "105 are not 105 defects" instruction was honoured literally.
- The 2 undeclared suites went into a
DIALECT_LEDGERas a measured baseline rather than marked, with the reason: "marking them would record a claim about intent I cannot verify". That is exactly the line I drew, held without being asked twice.
Independent corroboration: the dev re-measured the population on
origin/mainate7480a8067and got 105 / 44 / 7 — my numbers exactly, from a separate measurement.One more piece of discipline worth naming: mid-branch the dev replaced its own hand-rolled
stripCommentswithscripts/js-comment-mask.mjs, the repo's single answer to "comment or code", and verified the census output was byte-identical across the swap — "a change of provenance and not of measurement" — then re-ran the ablation from scratch because the detector had changed.
Answering both open questions — PM rulings, measured not argued
Q1 — the two ledgered suites: option A, as a follow-up card
I measured both halves rather than taking the recommendation:
claim measurement on origin/mainicontainsis already matrix-covered by another suitesql-driver-text-case-conformance.test.tsmentionsicontains16 times, and routes through the testkit ✅the comparand-type case-set claims universality it does not measure check-driver-conformance.mjs:231, verbatim: "the comparand-type door: the six accepted types compile everywhere, everything else is refused loudly — #7872" ✅⇒ A is right, and the dev's concession toward B is unnecessary.
icontainsgenuinely is covered on all three dialects by its neighbour, sosql-driver-icontains-and-retired-operators.test.tsis a second pass over covered ground and marking itdialectCell('sqlite')loses nothing. B would convert a suite that adds no dialect coverage.The comparand-type conversion is the one that is earned: it is the only dialect-scored cell with no matrix-routed suite at all, against a case-set whose own prose claims the accepted types compile everywhere. A claim of universality measured on one dialect is precisely this card's thesis, one level in.
⚠️ The dev's argument for B — thatFILTER_TEXT_CASESis the case-set known to diverge (#6518: GLOB on SQLite, LIKE on Postgres, LIKE overCAST(.. AS BINARY)on MySQL) — is a good argument and would have been decisive if that cell were uncovered. It is not; that is what the 16 hits settle.Q2 — promoting the invariant: option B, and it becomes free
Leave "every dialect-scored cell has at least one matrix-routed suite" as a printed measurement here. Promoting it now would red exactly one cell (
FILTER_COMPARAND_TYPE_CASES) and clearing that red needs a test-file edit — the coupling my dispatch explicitly ruled out, and refusing it was correct rather than cautious.The chain closes cleanly: the follow-up card converts comparand-type to the matrix and marks icontains → the population becomes zero → the promotion costs nothing → the invariant lands and ADR-0053 D-A3 is enforced rather than reported. That promotion is the follow-up's closing step, not a separate card.
Filing that follow-up now. My dispatch said this card's number should size it; the number is 2.
Also carried out: #12135 —
consumes()scores a comment-only mention as coverage, sosql-driver.ts(the driver implementation, not a suite) is counted as coveringFILTER_LOGIC_CASESon two prose mentions. Its dedup note correctly declares the REST 403 rather than claiming an empty search as evidence (#12123).Flipping to ready and enqueueing once CI converges.
Generated by Claude Code
- One file changed —
LANDED — PR #12134 merged as
dd391cee42.Verified by content on
origin/main:DIALECT_LEDGER→ 6 occurrences (0 before).The census now has the third axis ADR-0053 D-A3 declares. The population is defined by the presence of a stance declaration rather than the absence of a
clientliteral — so moving a driver config into a helper can no longer respell a suite out of the gate's reach. Scoring is per file, becauseFILTER_TEXT_CASESis covered by both a matrix suite and an undeclared one and per-cell scoring would let the undeclared one hide.The ablation is what closes it: the old census returned
exit 0, 45 covered cell(s)on both a clean tree and one with a testkit import broken —diffof the two runs empty. That is #12014 demonstrated rather than described.Both open questions were answered at PM level on measurement, and the follow-up is #12136, sized at 2 as this card's own number required.
Closing as completed;
pm:dispatchedstripped in the same stroke.
Generated by Claude Code
Observed while converting
sql-driver-aggregation-conformance.test.tsto the live-dialect matrix (#11456). Filed unassigned as an observation about gate reach, not a defect with a settled fix.What was observed
pnpm check:driver-conformancereports, onorigin/mainand on the #11456 branch alike:The two readings are identical — before and after a change whose entire content is "this conformance suite went from executing on one dialect to executing on three". That is correct behaviour for the gate as written: its matrix axes are
driver × case-set. It has no dialect axis, so dialect coverage is not a thing it can score.Why it matters
ADR-0053 D-A3 states the matrix is
driver {SQLite, Postgres at minimum}. That axis is enforced only from inside a suite — by routing throughlive-dialect-matrix.testkit.tsand byOS_EXPECT_LIVE_DIALECT_MATRIX=1turning an unprovisioned cell into a named red. Both are opt-in: they fire only for a file that already opted in.So a conformance suite that hard-codes
client: 'better-sqlite3'is invisible to every gate in the repo. It is green, it is counted as a covered cell in the census, and nothing anywhere says it measured one third of what its name claims. That is precisely how #11456 sat unnoticed — measured on live PG 16.13 there,sum/avg/min/maxover a boolean column threw SQLSTATE42883while the suite was green onmain, on every PR.The testkit's own head note already names the shape ("a hard-coded client is invisible... declared != enforced"), and
sql-driver-temporal-conformance.test.tscarried four of them while claiming otherwise. This card records that the census does not close it either.What is NOT being claimed
Measured in
packages/drivers/driver-sql/srcat1958979fc6: 99 test files construct a driver with a literalclient: 'better-sqlite3', and 40 route through the testkit. ⛔ Those 99 are not 99 defects — most are legitimately SQLite-specific (sql-driver-11321-sqlite-audit-default-canonical.test.tsis about SQLite by name). The gap is that nothing distinguishes "deliberately single-dialect" from "accidentally single-dialect", and the two are spelled identically today.That is the reach question, and it is why this is filed rather than fixed: closing it means deciding what marks a deliberate single-cell suite (an explicit
dialectCell('sqlite')call is one candidate — it already exists for exactly that purpose, and 7 files use it alongside the literal), and that is a convention decision, not a mechanical edit.Related: #11456 (the instance), #11455, #11249.