You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
test(drivers): collapse ContainsAny's distributivity so union-shaped doors assert (#18029)
Fixes#17970
Clause-②: no
⚠️ Generic angle brackets are spelled with SQUARE brackets throughout
this body. The GitHub body sanitizer eats tag-shaped fragments,
backticks and fences included, so `ContainsAny[T]` below means the
ordinary generic spelling.
`ContainsAny` — the type-level `any` detector #17690 installed in these
two door-pinning test files — distributes over unions. Every
union-shaped door therefore evaluated to `boolean` once regressed, and
because each leg is spelled `const x: ContainsAny[Door] = false` and
`false` is assignable to `boolean`, the leg compiled straight through
the regression it exists to name. The phantom leg the detector was
installed to close was still open on the detector itself.
⛔ This does not make #17690 wrong. Its nested-`any` reading is genuinely
effective on NON-union doors — `Record[string, any]` answers `true`
under both the old and the new spelling, and that is the control which
proves it. Union distribution was a SECOND blind spot standing beside
it, never a correction of it.
## What changed
Exactly two files, both `.test.ts`:
-
`packages/drivers/driver-sql/src/sql-driver-doors-declared-types.test.ts`
-
`packages/drivers/driver-turso/src/turso-driver-doors-declared-types.test.ts`
Option **B** (central), per the dispatch order's Zone 1. The per-member
walk is unchanged and keeps its own name, `ContainsAnyPerMember[T]`;
`ContainsAny[T]` is now its collapse — `ContainsAnyPerMember[T] extends
false ? false : true` — so it answers `false` only when EVERY union
member answered `false`. `IsAny` is untouched. No export, no published
payload key and no acceptance set is touched, which is why Clause-②
stays `no`.
The detector's own docblock is rewritten in the same change. Before
this, its closing sentence read: "The branch order matters: `IsAny[T]`
is asked FIRST so a bare `any` never reaches a distributive conditional,
where it would split across both arms and answer `boolean`." That
sentence's scope changes once the union case is fixed — the branch order
is now one of TWO guards, not the guard — so leaving it would have left
a half-true statement behind the fix. It now names both guards, what
each one does NOT cover, and the measurement.
## Measurements
Every line below is a measurement unless marked 【expectation】. There are
none marked 【expectation】.
### 1. Detector semantics — standalone `tsc --strict` program, 29
asserted equalities
Instrument: a file with no repo imports carrying the old detector text
verbatim from `origin/main` `2f1a6f6968` and the new one side by side;
each claim is an `Eq[X, Y] = true` const, so tsc reds any claim that
does not hold.
- probe :: **exit 0** — all 29 equalities hold.
- FIRING CONTROL, three deliberately-false claims in the same instrument
:: **exit 2, 3 errors** — so the green above is a reading, not an inert
file.
| shape | old detector | new detector |
|---|---|---|
| `Record[string, unknown]` | `false` | `false` |
| `Record[string, unknown][]` | `false` | `false` |
| `unknown` | `false` | `false` |
| `Record[string, unknown] | null` | `false` | `false` |
| `Record[string, unknown] | undefined` | `false` | `false` |
| `{ k?: boolean } | undefined` | `false` | `false` |
| `any` | `true` | `true` |
| `any[]` | `true` | `true` |
| `Record[string, any]` | `true` | `true` |
| `Record[string, any][]` | `true` | `true` |
| `Record[string, any] | null` | ⛔ `boolean` | ✅ `true` |
| `Record[string, any] | undefined` | ⛔ `boolean` | ✅ `true` |
| `{ k?: any } | undefined` | ⛔ `boolean` | ✅ `true` |
The three `boolean` rows are the defect, and the probe also compiles
`const leg: OldDetector[RegressedUnionDoor] = false` for each of them,
which is what "the leg stays green" means in bytes.
⚠️ One correction, recorded rather than quietly re-run: my first probe
claimed the NON-regressed optional-options door answered `boolean` under
the old detector. tsc refused that claim. It answers `false` — a union
of clean members is `false` under both detectors, and the blindness
appears only when one member carries `any` and another does not. The
claim was corrected and the probe re-run.
### 2. No false positives — the real doors
`pnpm --filter @objectstack/driver-sql --filter
@objectstack/driver-turso typecheck` :: **exit 0** after the change.
That covers all 19 `ContainsAny[Door] = false` legs plus everything else
in both programs, so Zone 1.1's switch-to-A condition did NOT trigger.
Both test files are proven to be IN their package's tsc program (`tsc
--noEmit --listFiles`, 1 hit each, 600 / 450 files listed) — the
`typecheck` script is not excluding them.
### 3. The regression now reds — ablation, four runs, each with its
restore proven
Each run: mutate the driver's own `findOne` return annotation to
`Promise[Record[string, any] | null]`, prove the mutation landed on disk
(`grep -c` of the deleted anchor AND of the injected text, before and
after), run the package's `tsc --noEmit`, restore via `git checkout HEAD
-- path`, then prove the restore by `git diff HEAD` being empty AND all
four blobs hashing equal to HEAD. `trap ... EXIT INT TERM` with absolute
paths. tsc reads the driver SOURCE here, not `dist` — `--listFiles`
shows `src/sql-driver.ts` / `src/turso-driver.ts` in the respective
programs — so no rebuild sits between the mutation and the reading.
| run | tree | package | errors | which legs |
|---|---|---|---|---|
| 1 | **after** this fix | driver-sql | **2** | `sqlFindOneHasAny` (the
`ContainsAny` leg) AND `sqlFindOneIsContract` (the `Equals` leg) |
| 2 | CONTROL: `origin/main` detector | driver-sql | **1** |
`sqlFindOneIsContract` only — `sqlFindOneHasAny` compiled through it |
| 3 | **after** this fix | driver-turso | **2** | `tursoFindOneHasAny`
AND `tursoFindOneIsContract` |
| 4 | CONTROL: `origin/main` detector | driver-turso | **1** |
`tursoFindOneIsContract` only — `tursoFindOneHasAny` compiled through it
|
Runs 2 and 4 reproduce the card's own reading independently. Runs 1 and
3 are the answer to the dispatch order's 【expectation】 about #17690's
`findOne` leg: it is a real assertion now, measured rather than cited,
in both files.
### 4. Suites
`pnpm --filter @objectstack/driver-sql --filter
@objectstack/driver-turso test` :: **exit 0** — driver-sql 2620 passed /
166 skipped, driver-turso 1248 passed.
### 5. Repo gates
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived **52** families for these two paths.
All 52 were run with `$?` captured BEFORE any pipe, and the record was
reconciled back with `--ran`:
> 52 derived famil(ies) accounted for — 49 run, 3 NOT-MEASURED (3
DERIVED from a recorded exit 3).
49 :: exit 0. Three :: **exit 3, PREREQUISITE NOT MET, so NOT MEASURED,
⛔ not a pass and not a failure** — `check:dual-build-cjs-loads`,
`check:lean-entry-closure`, `check:type-check-debt`. All three refuse
because they load BUILT entry points across the whole repo and only this
card's two packages are built locally. CI builds everything, so CI
measures them.
## Changeset grading — `skip-changeset`
The criterion is whether the changed TEXT reaches `dist`, ⛔ not whether
any `dist` byte moves. Measured after rebuilding both packages from the
post-change source, grepping only the paths `files[]` actually ships
(`dist`, `README.md`, `CHANGELOG.md`):
| symbol | driver-sql `dist` | driver-turso `dist` |
|---|---|---|
| `ContainsAnyPerMember` (added text) | 0 files | 0 files |
| `ContainsAny` (changed text) | 0 files | 0 files |
| "never reaches the distributive arms" (added docblock) | 0 files | 0
files |
| POSITIVE CONTROL `SqlDriver` / `TursoDriver` | 4 files | 4 files |
| POSITIVE CONTROL `temporalFilterValue` | 4 files | — |
Zero hits for the changed text against a firing positive control, and
zero `.test.*` files emitted into either `dist` at all. One honest
complication, checked rather than assumed: the literal string
`doors-declared-types` DOES appear in both dists — it comes from TSDoc
in `sql-driver.ts` / `turso-driver.ts` naming the pin file, which this
diff does not touch. ⇒ nothing published moves. `skip-changeset`,
applied as a label.
## Acceptance notes
- **The `ContainsAny` detector exists in exactly these two files.** `git
grep 'type ContainsAny'` returns 4 lines, all in this diff. There is no
third copy to keep in sync, and no shared definition was touched.
- **11 further test files still carry the bare `IsAny` template**, which
is the phantom check #17690 replaced here — including the two
`driver-memory` files frozen by #5499
(`memory-find-create-declared-types.test.ts`,
`memory-update-declared-null.test.ts`) and
`turso-driver-options-door.test.ts`. Noted, NOT filed: this is #17879's
surveyed territory and the freeze lane's for the two `driver-memory`
files, both of which have a named owner. Triage on this card already
ruled the #5499 exception channel does not open here, so those files are
deliberately untouched and the net benefit of this change to the frozen
family is zero — which does not change its value on the doors outside
the freeze.
Session: https://claude.ai/code/session_01RuoNSXUbBoWHkNS4AknTrM
---
_Generated by [Claude
Code](https://claude.ai/code/session_01RuoNSXUbBoWHkNS4AknTrM)_
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments