Skip to content

[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

@os-warren

Observed while converting sql-driver-aggregation-conformance.test.ts to 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-conformance reports, on origin/main and on the #11456 branch alike:

driver conformance matrix (5 drivers x 9 case-sets)
check-driver-conformance: OK — 45 covered cell(s), 0 in the DEBT ledger, 0 exempt.

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 through live-dialect-matrix.testkit.ts and by OS_EXPECT_LIVE_DIALECT_MATRIX=1 turning 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/max over a boolean column threw SQLSTATE 42883 while the suite was green on main, 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.ts carried 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/src at 1958979fc6: 99 test files construct a driver with a literal client: '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.ts is 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.

Activity

  1. yinlianghui-tw commented on Aug 25, 2026

    @yinlianghui-tw
    Collaborator

    Triage: 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 as driver × {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: give check:driver-conformance the dialect axis, with the deliberate-vs-accidental distinction carried by an explicit marker — the existing dialectCell('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 $comment discipline (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

  2. os-warren commented on Aug 25, 2026

    @os-warren
    CollaboratorAuthor

    Claim: PM loop (domain:engine seat)
    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 card

    The card measured packages/drivers/driver-sql/src a day ago. Measured again just now on origin/main:

    card now delta
    files with a literal client: 'better-sqlite3' 99 105 +6
    files routing through live-dialect-matrix 40 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.mjs and packages/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.ts bands 8600–9200 (#12015), 10100–10560 (#11722) and 13275–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.ts is 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 main and on every PR while, on live PG 16.13, sum/avg/min/max over a boolean column threw SQLSTATE 42883.


    Generated by Claude Code

  3. self-assigned this
    on Aug 25, 2026
  4. os-warren commented on Aug 25, 2026

    @os-warren
    CollaboratorAuthor
    {
      "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

  5. os-warren commented on Aug 25, 2026

    @os-warren
    CollaboratorAuthor

    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

  6. os-warren commented on Aug 25, 2026

    @os-warren
    CollaboratorAuthor

    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 — diff of the two runs is EMPTY

    That 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 a client literal. 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_CASES is 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.ts edits, 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_LEDGER as 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/main at e7480a8067 and 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 stripComments with scripts/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/main
    icontains is already matrix-covered by another suite sql-driver-text-case-conformance.test.ts mentions icontains 16 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. icontains genuinely is covered on all three dialects by its neighbour, so sql-driver-icontains-and-retired-operators.test.ts is a second pass over covered ground and marking it dialectCell('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 — that FILTER_TEXT_CASES is the case-set known to diverge (#6518: GLOB on SQLite, LIKE on Postgres, LIKE over CAST(.. 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, so sql-driver.ts (the driver implementation, not a suite) is counted as covering FILTER_LOGIC_CASES on 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

  7. os-warren commented on Aug 25, 2026

    @os-warren
    CollaboratorAuthor

    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 client literal — so moving a driver config into a helper can no longer respell a suite out of the gate's reach. Scoring is per file, because FILTER_TEXT_CASES is 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 — diff of 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:dispatched stripped in the same stroke.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions