Skip to content

feat(drivers): lower count_distinct on the SQL family — the enforce half of the #6188 ruling (#6409) - #6816

Merged
os-zhuang merged 5 commits into
mainfrom
claude/issue-6409-count-distinct-sql-family
Aug 8, 2026
Merged

feat(drivers): lower count_distinct on the SQL family — the enforce half of the #6188 ruling (#6409)#6816
os-zhuang merged 5 commits into
mainfrom
claude/issue-6409-count-distinct-sql-family

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #6409

Premise, re-verified before implementing

The issue's lead held. On origin/main @ 6de592c, both SQL faces refused count_distinct with NOT_IMPLEMENTED / 501, and the two pin files recorded it as the sole inhabitant of #5907's class 2. The issue's line anchors had drifted (as the dispatch predicted) — mapAggregateFunc is at sql-driver.ts:8035 on this branch, not :7071 — but the shape was exactly as described.

One thing the issue's framing understates and this PR had to handle: AggregationFunction declares six values and SQL_AGGREGATE_FUNCTIONS compiled five, so landing the sixth empties class 2 entirely. That is not a side effect to tidy — it is a decision about #5907's capability-gap producer, taken explicitly below.

What changed

The lowering, on both faces in one change

  • packages/drivers/driver-sql/src/sql-driver.tsSQL_AGGREGATE_FUNCTIONS now maps each name to a SqlAggregateLowering record ({ sql, distinct }) instead of a bare SQL function name, and SqlDriver.aggregate emits count(distinct ??) for the distinct entry. The column is still bound as a knex identifier; the keyword is fragment text, never a binding.
  • packages/drivers/driver-turso/src/remote-transport.ts — the twin, RemoteTransport.aggregate, emitting count(distinct "column") through its own hand-built SELECT list.

Both faces, one change, deliberately: TursoDriver picks between them from url, so a lowering that landed on one alone would be #6203's shape again — one query, two answers, decided by a connection string.

mapAggregateFunc's return type moved from string to the record. It is protected and had exactly one caller in tree; every entry answering { sql, distinct: false } compiles to byte-identical text to what the string return produced.

Semantics: distinct NON-NULL values

Measured rather than assumed, against a real better-sqlite3 database (local face) and SQLite behind the libsql interface (remote face): COUNT(DISTINCT col) excludes NULLs on both. That matches the standard's definition of COUNT over non-null values (PostgreSQL, MySQL alike), and matches what objectql's in-memory fallback and service-analytics's AGGREGATE_SQL already answer. The fixture pins it: count(*) is 6, count(stage) is 4, count_distinct(stage) is 2 — three different numbers over one column, so a lowering that collapsed into either neighbour fails on a value.

field is now required for count_distinct — a new refusal

AggregationNodeSchema makes field optional because COUNT(*) is a real spelling and the schema cannot say "optional for this function, required for that one". So { function: 'count_distinct', alias: 'n' } parses, reaches the driver, and asks for COUNT(DISTINCT *) — a syntax error in every dialect. Both faces now refuse it up front with INVALID_QUERY / 400 and a message naming the fix, rather than emitting it and letting a dialect error arrive as an opaque 500 (mapDataError's default branch — the #1116/#1117 gap #5907 closed at this same door).

Class 1, not class 2, and the messages say so: the function is compiled here; it is this aggregation node that is malformed. Plain count with no field still means COUNT(*), pinned by a control on each face.

Class 2 is now empty — and its producer is kept, on purpose

With count_distinct lowered, AggregationFunction and each face's compiled vocabulary are the same set, so uncompilableAggregateFunctionError has nothing to produce.

Deleting it as dead code was considered and rejected. That branch is not an unenforced declaration — the ADR-0049 shape — it is the classifier deciding which of two truths a future name is told. Removing it does not remove the condition; it makes refuseAggregateFunction answer 400 for the first function a later spec bump adds, telling the author of a correctly-spelled name that the protocol has no such function. That is precisely the misreport #5907 exists to prevent, and it would land in the window ADR-0049's enforce leg opens on purpose — the window #6188 just opened for this very name. Cost of keeping: one unreachable branch. Cost of dropping: a wrong answer at the moment the vocabulary grows.

Both pin files assert the emptiness positively (the declared-but-uncompiled set is EMPTY), so a spec addition goes red there rather than quietly leaving the block covering nothing.

The rejection message

Both faces build their Compiled here: list from the lowering table, so it now reads count, sum, avg, min, max, count_distinct. Asserted off a real refusal on each face, not off a literal — the acceptance criterion "the rejection message no longer names count_distinct as unsupported", made checkable.

Shared conformance — the multi-face rule

New shared case-set: packages/spec/src/data/aggregation-conformance.tsAGGREGATION_ROWS (six rows, two groups, a nullable duplicate-bearing column) and AGGREGATION_CASES (twelve cases covering the whole compiled vocabulary, ungrouped and grouped). Not a standalone test file: the two SQL lowerings are pinned against each other, on values, which is the only instrument that can see this class of bug — every wrong count_distinct lowering still emits valid SQL and returns a plausible number.

Driven by three suites, all executing against a real engine:

Face Suite Engine
driver-sql sql-driver-aggregation-conformance.test.ts better-sqlite3
driver-turso REMOTE turso-remote-aggregation-conformance.test.ts makeLibsqlSqliteStub
driver-sqlite-wasm sqlite-wasm-aggregation-conformance.test.ts sql.js dialect

scripts/check-driver-conformance.mjs classifies the new column (it failed CLASSIFIED until it did — the gate working as designed). The two remaining cells carry honest DEBT rows, measured from the source, not flipped and not faked:

  • driver-memoryMemoryDriver.computeAggregate has no count_distinct arm; the switch falls to default: return null, so the aggregation resolves with { n: null }. A wrong answer, not a wrong number.
  • driver-mongodbcount_distinct lowers to $addToSet and is sized by .length, so an explicit null counts as a distinct value: 3 where the standard says 2.

Both are inside the #5499 freeze and #6409's ruling put them explicitly out of scope; their partial implementations are untouched. Filed as #6814 so the rows point at a tracked decision rather than at a note.

Pins flipped, and what replaced them

sql-driver-out-of-contract-aggregate-function.test.ts and remote-transport-aggregate-function-refusal.test.ts both recorded count_distinct -> 501. Flipped, never merely deleted — each old assertion was replaced by the new substance: the empty-set assertion, the emitted count(distinct …) / the computed value, and the refusal wording that now lists the function as compiled. The remote file's parity block loses count_distinct as a refusal case and gains two: both faces answer it identically, and both refuse the field-less spelling identically (INVALID_QUERY/400, one wording).

Class 1 is untouched throughout — median, array_agg, string_agg and every miscased spelling are still undeclared names, and their refusals stay verbatim. A pin is flipped only where the fact under it moved.

Reverse verification — predicted, then measured

Two reverts on both faces, direction written down before running.

(A) the count_distinct entry deleted (the pre-#6409 state). Predicted: the count_distinct cases fail by throwing 501, never on a value. Measured: local 5 failed / 11 passed of 16, remote 6 failed / 11 passed of 17 — every value case on the thrown 501, none on a number. One failure was not predicted and is recorded rather than tidied: the new field-less refusal case went red on expected 'NOT_IMPLEMENTED' to be 'INVALID_QUERY', which is what proves the two refusals are distinguishable rather than interchangeable.

(B) distinct flipped to false — the copied-neighbour mistake, and the one a review that only checked the two faces' tables have the same keys would pass. Predicted: failures on VALUES, with count_distinct(score) staying green because that column has nothing to dedup. Measured: local 4 failed / 12 passed, remote 5 failed / 12 passed, on expected 4 to be 2 and west 3 vs 2 — the same two wrong numbers on both faces, and count_distinct(score) green throughout, exactly as predicted. That agreement is the pairing doing its job.

(B) is the direction this table exists for; (A) is reachable by any test that merely calls the function.

Spec-side wording

  • AggregationFunction's JSDoc: count_distinct no longer "leads its implementation"; the NULL semantics and the required field are stated.
  • AGG_RETIRED_MIDDLE (the live array_agg/string_agg parse-error prescription) said the two SQL faces "lower the same five functions", which this PR makes false. Corrected to "the same set" — one character shorter, deliberately: packages/rest's analytics-dataset-refusal-envelope.test.ts asserts that the actionable "Delete the aggregation" survives the detail truncation window, and a longer edit pushed it out. Caught by that test, not by review.

The #6188 conversion/migration registry entries are not touched: they narrate the state at that ruling and already say the SQL lowering "follows on its own card". Historical narration, accurate as history.


os-dev report

Issue: #6409 — implement count_distinct in the SQL family (the enforcement half of the #6188 ruling)
PR: #6816 (draft) · branch claude/issue-6409-count-distinct-sql-family · head 08f803e
premise_still_valid: true
CI: green — all 25 checks completed success or skipped on 08f803e.

(The sections above are the detail; this is the structured summary, posted identically as a comment on #6409.)

Gates and tests

  • The gate list enumerated from .github/workflows/lint.yml, run step by step (not from memory): 58 / 58 PASS. Workspace built first so the check:i18n / check:i18n-coverage / check:app-nav-i18n trio ran for real; each step's exit status read directly, never through a pipe.
  • Two failed on the first pass and both were fixed here, not worked around: check:driver-conformance (CLASSIFIED — the new case-set was unregistered) and check:api-surface (five new exports; snapshot regenerated with gen:api-surface).
  • Tests: driver-sql 1095✓/48 skipped · driver-turso 902✓ · driver-sqlite-wasm 302✓ · driver-memory 540✓ · driver-mongodb 214✓/143 skipped · spec 8861✓ · objectql 2656✓ · service-analytics 1415✓ · metadata-protocol 740✓ · rest 1097✓.
  • Workspace-wide turbo run typecheck (120 tasks) and both enumerated turbo run build filters: green.

One CI round was red, and it is worth recording why the local gate list did not catch it. TypeScript Type Check failed on 9b9b429 with src/sql-driver-aggregation-conformance.test.ts(121,63): error TS2353: 'sort' does not exist in type 'DriverQuery' — the fixture read-back used sort where QueryAST declares orderBy. My enumeration from lint.yml transcribed the check:* steps but omitted the workspace-wide turbo run typecheck / turbo run build steps in the same workflow, and the per-package typecheck I had run was run before that suite was written. Fixed in 08f803e, and the two missing commands were then run locally and are green. The lesson is the enumeration's, not the type error's: "every check:* step" is narrower than "every step".

Out-of-scope findings (search-first dedup, filed unassigned)

Open questions for the maintainer (三轴自裁, recorded not blocked)

  1. The kept-but-unreachable class-2 producer. Judged: keep, on the argument above. If the maintainer prefers ADR-0049's letter over the misreport risk, deleting uncompilableAggregateFunctionError on both faces is a small follow-up — the positive emptiness assertions are already in place to make the deletion honest.
  2. AGGREGATION_CASES' enrolment boundary. Enrolled the three SQL-family drivers. objectql's in-memory fallback is a fourth lowering that agrees with the table and is not frozen; it is recorded in the case-set as a candidate rather than a debt, because reaching it needs the engine rather than a driver. Enrolling it is a judgement call I left to the seat that owns the objectql lane.
  3. service-analytics's AGGREGATE_SQL is a fifth COUNT(DISTINCT …) lowering (the Cube face). Left unenrolled on scope discipline — drivers: implement count_distinct in the SQL family — enforcement half of the #6188 ruling #6409 named the driver family — but it is the obvious next column if the table is meant to cover every SQL-emitting face.

Not done, and why

Nothing in the issue's scope was skipped. driver-memory / driver-mongodb are out of scope by the ruling and stayed untouched; their verdicts are DEBT rows, not changes. content/docs/releases/ untouched. The #6188 conversion/migration registry entries were left alone — accurate as history.

claude added 4 commits August 8, 2026 21:10
Implementation half of the #6188 split ruling: count_distinct stays
declared and now compiles to COUNT(DISTINCT column) on driver-sql's
SqlDriver.aggregate and driver-turso's RemoteTransport.aggregate.

Adds the shared AGGREGATION_CASES conformance table so the two faces are
pinned against each other on values rather than on a side-by-side read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWMbS2ctjZSADPJiSdUtMA
…nce, add changeset (#6409)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWMbS2ctjZSADPJiSdUtMA
…trix (#6409)

Enrols driver-sql, driver-turso and driver-sqlite-wasm; records honest DEBT
rows for the two #5499-frozen packages (tracked as #6814). Regenerates the
spec API surface for the new shared exports.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWMbS2ctjZSADPJiSdUtMA
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 10:49pm

Request Review

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/driver-sql, @objectstack/driver-turso, @objectstack/spec.

116 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/driver-sql, @objectstack/driver-turso, @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/driver-turso, @objectstack/spec)
  • content/docs/deployment/environment-variables.mdx (via @objectstack/driver-turso)
  • content/docs/deployment/self-hosting.mdx (via @objectstack/driver-turso)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/glossary.mdx (via @objectstack/driver-sql, @objectstack/driver-turso)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/anatomy.mdx (via @objectstack/driver-sql)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/driver-sql, @objectstack/driver-turso, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/driver-sql, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added size/xl documentation Improvements or additions to documentation protocol:data tests tooling labels Aug 8, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 8, 2026 22:48
…erQuery declares (#6409)

`sort` is not a member of QueryAST; the fixture read-back compiled locally
only because the package typecheck had not been re-run since the suite was
written. Caught by CI's workspace typecheck, which the local gate enumeration
had missed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWMbS2ctjZSADPJiSdUtMA

Copy link
Copy Markdown
Contributor Author

ACCEPT — drivers lane, PM dispatch loop. Step-7 gate passed on all six criteria, each verified against the diff and the JOB logs rather than off the report's own claims.

Criterion Evidence taken independently
Both SQL faces, one change sql-driver.ts +144 and remote-transport.ts +115 in the same change — not one face with the other left to drift on a connection string.
The flipped refusal pin bears new substance The two pin files add +82 / +137 lines against 42 / 27 removed. The old count_distinct → 501 assertions are replaced by a positive empty-set assertion, the emitted count(distinct …), and value pins — not deleted into silence.
Frozen packages untouched Zero driver-memory / driver-mongodb source files in the diff.
Per-dialect NULL semantics measured, not assumed The fixture pins count(*)=6, count(stage)=4, count_distinct(stage)=2 over one nullable column, so a lowering that collapses into either neighbour fails on a value; harnesses are required to seed the nulls as nulls.
Honest DEBT, no fake green Both frozen cells are DEBT, labelled "read from source, not executed", pointed at #6814. Neither flipped.
Rejection asserts code AND status expect(remote.code).toBe('INVALID_QUERY') + expect(remote.status).toBe(400), plus cross-face equality — never a bare toThrow.

CI gated on the JOB conclusions: 26 check runs on 08f803e, all success or skipped — including TypeScript Type Check, all three Test Core shards, Dogfood Regression Gate, Temporal Conformance (live PG + MySQL) and Check Changeset.

Two things the seat is recording as credit rather than passing over:

  1. 08f803e was self-caught. sort:orderBy: — the key DriverQuery actually declares. With sort the option was silently ignored and the conformance read-back was unordered, so the suite could pass on insertion-order luck. The report names the enumeration error behind it (check:* steps transcribed, workspace-wide turbo run typecheck omitted) instead of reporting the fix alone. "Every check:* step" being narrower than "every step" is the reusable lesson.
  2. Class 2 emptied with its producer kept, argued rather than tidied. Keeping an unreachable uncompilableAggregateFunctionError is the right call: deleting it makes refuseAggregateFunction answer 400 to the first correctly-spelled name a later spec bump adds — the exact misreport drivers(sql,turso): Unsupported aggregate function 两面都是裸 Error(code/status 皆 undefined),且三个 spec 已声明的聚合函数无任何 SQL 后端编译 #5907 exists to prevent. The positive emptiness assertions make that choice re-decidable later.

The three open questions (producer deletion; enrolling objectql's in-memory fallback; enrolling service-analytics's AGGREGATE_SQL as a fifth COUNT(DISTINCT …) face) are recorded, not blocking, and correctly left to the seats that own those lanes.

Marking ready and enabling auto-merge. The full suite runs again on the speculative merge result in the queue; per #4859 a red queue build gets diagnosed before any requeue, not blind-requeued.


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation protocol:data size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

drivers: implement count_distinct in the SQL family — enforcement half of the #6188 ruling

2 participants