@@ -161,6 +161,11 @@ const CASE_SETS = [
161161 marker : 'FILTER_TEXT_CASES' ,
162162 what : 'text operators: ASCII-only case folding, literal comparands, `$regex` refused — #4706/#5701' ,
163163 } ,
164+ {
165+ file : 'aggregation-conformance.ts' ,
166+ marker : 'AGGREGATION_CASES' ,
167+ what : 'the value each declared AggregationFunction produces, dedup and NULLs included — #6409' ,
168+ } ,
164169] ;
165170
166171// ── The ledger ──────────────────────────────────────────────────────────────
@@ -328,8 +333,24 @@ const CASE_SETS = [
328333// `code` half the case-set requires and the last place a bare `new Error`
329334// escaped the ADR-0112 envelope.
330335//
331- // Each row's `why` is what that driver does TODAY, measured on this branch by
332- // reading the compiler and executing it. Nothing here is predicted.
336+ // ## AGGREGATION_CASES: two DEBT rows on arrival, and they are the same pair
337+ //
338+ // The column arrived with #6409, which lowered `count_distinct` to
339+ // `COUNT(DISTINCT x)` on the SQL family — the ENFORCE leg of #6188's split
340+ // ruling. Three of the five cells were covered by that PR: `driver-sql` and
341+ // `driver-turso` (its REMOTE transport, an independent compiler, which is what
342+ // the case-set exists to hold against the local one) plus `driver-sqlite-wasm`,
343+ // whose suite pins the inherited statement surviving a different ENGINE, the
344+ // same judgement #4405 recorded for its filter-logic cell.
345+ //
346+ // The two open cells are `driver-memory` and `driver-mongodb` — the #5499 frozen
347+ // family, and open by that decision rather than by difficulty. #6409's ruling
348+ // put both explicitly out of scope and left their partial implementations
349+ // untouched, so the rows below record what each ANSWERS today, read from the
350+ // source on this branch. Neither is a prediction, and neither is a permission
351+ // slip: the cell clears when a suite runs the case-set, not when someone argues
352+ // the driver would pass it. Both would go RED as they stand, which is the
353+ // reason the rows exist rather than a reason to omit them.
333354
334355const LEDGER = [
335356 {
@@ -381,6 +402,41 @@ const LEDGER = [
381402 + 'this cell needs a server-free half like `mongodb-filter-logic-translation.test.ts` has.' ,
382403 issue : 'https://github.com/objectstack-ai/objectstack/issues/6682' ,
383404 } ,
405+ {
406+ driver : 'driver-memory' ,
407+ marker : 'AGGREGATION_CASES' ,
408+ kind : 'DEBT' ,
409+ why :
410+ 'Measured on this branch by reading `MemoryDriver.computeAggregate` (`memory-driver.ts`): it has arms '
411+ + 'for count/sum/avg/min/max and then `default: return null`. There is NO `count_distinct` arm, so an '
412+ + 'aggregation the Query Protocol declares — and that every SQL face now lowers (#6409) — resolves with '
413+ + '`{ n: null }`: no error, no log, no refusal. The case-set says 2 over `AGGREGATION_ROWS`. That is a '
414+ + 'wrong ANSWER rather than a wrong number, and it is the `default:`-arm shape the '
415+ + '`aggregation-lockstep` guard exists to stop one layer up, reached here through a different door. '
416+ + 'The package is partial in the way #6409\'s ruling described: its ANALYTICS face '
417+ + '(`memory-analytics.ts`) DOES implement `count_distinct`, so this package answers one declared '
418+ + 'function two ways depending on which face you enter — the divergence class #5374 fixed for '
419+ + '`$contains` in this same package. #5499 freezes it, so the cell is open by decision, not by '
420+ + 'difficulty: the fix is one arm beside its neighbours. Tracked as #6814.' ,
421+ issue : 'https://github.com/objectstack-ai/objectstack/issues/6814' ,
422+ } ,
423+ {
424+ driver : 'driver-mongodb' ,
425+ marker : 'AGGREGATION_CASES' ,
426+ kind : 'DEBT' ,
427+ why :
428+ 'Measured on this branch by reading `mongodb-aggregation.ts`: `count_distinct` lowers to '
429+ + '`{ $addToSet: fieldRef ?? null }` and `postProcessAggregation` takes the array\'s `.length`. '
430+ + '`$addToSet` adds an explicit `null` to the set, so a nullable column sizes ONE HIGHER than '
431+ + '`COUNT(DISTINCT col)` does — 3 where the case-set says 2 over `AGGREGATION_ROWS`. `$addToSet` on a '
432+ + 'MISSING field adds nothing, so the divergence shows only for an explicitly-null value, which is '
433+ + 'exactly what the fixture seeds and what a nullable column produces in practice. Not executed — this '
434+ + 'package has no suite for the cell, which is the debt. #5499 freezes it; the fix is a `$ne: null` '
435+ + 'before the `$addToSet` (or sizing a `$setDifference` against `[null]`). Tracked as #6814. Note the '
436+ + 'real-mongod suites are opt-in since #5517, so whatever clears this cell needs a server-free half '
437+ + 'like `mongodb-filter-logic-translation.test.ts` has.' ,
438+ issue : 'https://github.com/objectstack-ai/objectstack/issues/6814' ,
439+ } ,
384440] ;
385441
386442// ── Discovery ───────────────────────────────────────────────────────────────
0 commit comments