Repository navigation
Commit bd28708
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1X6BFuP3Yn7kQNxWcwpUBnAP)_
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
Cut 7 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6415078284`. The body of the protected
`SqlDriver#resolveHashShadowKeys`, the MySQL hash-shadow enrichment of
the index read, moves unedited into
`packages/drivers/driver-sql/src/sql-driver-introspection.ts`, beside
`introspectIndexes`, its only caller (cut 5). It reaches the class
through that module's existing host, `IntrospectionHost`, which already
lists `knex` and `resolveHashShadowKeys`, so **the host is not
widened**. The method keeps its name, docblock, signature (less `async`)
and position.
It is move-only, and the card stays open for the later cuts. Branch
`claude/project-thread-3jc3ll` (platform-assigned to this card thread,
as the claim records). The cut commit `0b01e18ba` sits on `origin/main`
`b4199c968`; seat 1's #26015 (`SqlDriver.upsert`) then landed, and
`origin/main` was merged in (`156e3538f`, merge base `0a6948210`, clean,
no conflict). Every reading below was taken on both pairs: base
`b4199c968` vs head `0b01e18ba`, and base `0a6948210` vs merged head
`156e3538f`.
**Net line count (the seat's rule from ACCEPT `6385306916`).**
`sql-driver.ts` goes from 21,449 lines to 21,431 on the merged pair
(21,398 to 21,380 on the first pair): **-18**. The body is 25 lines out;
the stub is 6 lines in; the introspection import gains one name (+1) and
its comment one line (+1); `isHashShadowCarrier` leaves the
`schema-drift.js` import (-1), since the moved body was its last value
read in the file. The module grows 927 to 975 lines. The slice pays
alone, so no hash-shadow neighbour was paired with it.
**Serial with the file's in-flight PRs.** Re-measured at my start: 40
open PRs, each file list read. The only one on
`packages/drivers/driver-sql/**`, `driver-turso/**` or
`driver-sqlite-wasm/**` was #26015 (upsert region at lines ~2256 and
~9495-10078, plus one import line after `unencoded-json-text.js`); this
cut's region is the introspection stub (~15134) and the import lines 126
and 163-173. `git merge-tree` of the cut against #26015's head
`b4fc36f35e` was clean; #26015 then landed first and this branch merged
`main` after it, as card ask 4 says. The Version Packages PR #25640's
file list could not be paged through the proxy (HTTP 403 on the
redirected page); it has carried only `CHANGELOG.md` and `package.json`
changes for these packages in every earlier cut.
## The area, measured on `0a6948210`
- `resolveHashShadowKeys` is lines 15134-15163 of `sql-driver.ts` (a
28-line docblock above it, 25 body lines). Its only caller is cut 5's
`introspectIndexes` body in `sql-driver-introspection.ts`, through the
host closure.
- Protected, with an annotated return type (a promise of `void`), so the
inferred-return limit does not bite.
- It does not build through `getBuilder` (it reads the catalog through
`this.knex.select(...).from('information_schema.COLUMNS')`), so
`check:tenant-chokepoint` rule 1 is untouched.
- No static read and no cast-wrapped `this` read (AST screen): the only
member it reads is `knex` (twice). It has no
`this.FIELD.delete/insert/update(` site.
- `TursoDriver` and `SqliteWasmDriver` do not override it (`git grep`
over both packages: 0 hits), and no test, script, doc or ADR names it
(`git grep` over `docs/`, `content/`, `scripts/`, `.github/`: 0 hits).
## The shape (#23050 shape B, as cuts 1-6 apply it)
- The class method keeps its docblock and signature, byte-identical less
`async`. Its body is one host literal plus
`resolveHashShadowKeys.call(host, tableName, indexes)`, marked `[#25521
cut 7]`, and it returns the moved function's own promise.
- `knex` goes as a GETTER that reads the driver at call time (the shape
cut 5's stub uses), so a `knex` replaced on the instance after
construction is the one the body reads.
- The moved function types its `this` as the `Pick` of
`IntrospectionHost` over `knex` alone, and the stub annotates its
literal as the `ThisParameterType` of the moved function. No cast, and
no member becomes public.
- `introspectIndexes`' body still calls
`this.resolveHashShadowKeys(...)` through its host closure, which calls
the class method on the driver. A subclass override or an instance spy
is still the one reached (probe below).
- **Module-level declarations.** The body reads `isHashShadowCarrier`
and `parseHashShadowKeyParts`, both exported by `schema-drift.ts`, so
the module imports them from there (not a copy). `sql-driver.ts` still
reads `parseHashShadowKeyParts` (two other call sites) and keeps it; it
no longer reads `isHashShadowCarrier` as a value (two prose mentions in
comments remain) and drops it from its import. No declaration gains an
`export`; `index.ts` re-exports nothing from the module.
- The module header gains a `[#25521 cut 7]` paragraph; the
`sql-driver.ts` import comment names cut 7.
- The move was produced by a script from the source text, not retyped:
each body line re-indented two columns. The body holds no template
literal.
## The published `.d.ts` does not change
Under the series bar (ruling `6348891160`, letter A). Each end built
with `pnpm --filter @objectstack/driver-sql build` against the same
dependency tree; the base legs restore the base text of the two files in
this worktree after the commits, under an EXIT/INT/TERM trap that
restores HEAD (proved by HEAD blob hashes, an empty `git diff HEAD` and
0 status entries).
- This package emits `dist/index.d.ts` and `dist/index.d.mts` (no
`.d.cts`); the two are identical at every end.
- First pair: raw sha256 of both files at base `b4199c968` and head
`0b01e18ba` is
`93da45168e82136b7613944525e47402d5dc6f9f8daa9efa4bdceeaa11b52a89` (cuts
1-6's hash); `cmp` identical.
- Merged pair: #26015 changed the published surface, so the hash moved
for both ends together: base `0a6948210` and merged head `156e3538f` are
both `5028e040e1501b0bd72b91fafcf4e1cb372393c59baa5bab8b936b240dd2d3f5`;
`cmp` identical.
- Positive control on a copy of the first-pair head `dist/index.d.ts`:
line 5750, the `protected resolveHashShadowKeys(tableName: string,
indexes: PhysicalIndex[])` declaration, with `protected` removed, gives
`766c5f27828eae19be82213dcfedb1fd5f4e52239fb3d6435fc9e5fa0c2f121f` and a
4-line diff; `cmp` exits 1.
- Export tables: the ESM and CJS bundles each export the same 56 names
at every end (sorted lists `diff`-identical).
- The head build carries the move: `.call(host` sites in
`dist/index.mjs` and `dist/index.js` go 18 to 19.
No changeset: `skip-changeset`, per ruling `6348891160` item 4
(move-only, no product behaviour change).
## Proof of move-only
TypeScript AST leaves (recursive `getChildren`, JSDoc skipped), base
`0a6948210` vs merged head `156e3538f` (and the same on the first pair):
- **Body**: 220 tokens, 0 differ; 1 comment, identical; parameters (less
the added `this`) 8 tokens, 0 differ; return type 4 tokens, 0 differ;
`async` matches.
- **Lines**: 27 body lines (braces included), each the base line with
two leading spaces removed.
- **Negative control**: in a copy of the module,
`'GENERATION_EXPRESSION'` in the `.select(...)` becomes
`'GENERATION_EXPRESSI0N'`. The check reports 1 token and 1 line
different and exits `PROOF FAILED`, exit 1.
- **Class side**: 348 members at both ends, same order; the 347 that did
not move are byte-identical, leading trivia included; the stub's leading
trivia and signature equal the base's, less `async`.
- **Top level of `sql-driver.ts`**: 207 statements at both ends; 204
byte-identical. The three that differ are the `schema-drift.js` import
(`isHashShadowCarrier` out), the `sql-driver-introspection.js` import
(`resolveHashShadowKeys` in, its comment rewrapped) and the class (the
one member above).
- **Top level of the module**: 11 to 12 statements; the first import
differs only by the header paragraph in its leading trivia, the
`schema-drift.js` import gains two names, and the new statement is the
moved function.
## Readers of `sql-driver.ts` by path, checked against the moved text
None needed an edit:
- **ADR anchors.**
`scripts/adr-anchors/packages__drivers__driver-sql__src__sql-driver.ts.json`
carries ADR-0053 and ADR-0120 D4; neither paragraph describes this body,
and the body cites no ADR, so no entry is owed. `check:adr-anchors`: 88
anchored files at both ends; decision-letter citations on the anchored
surface **1,878 at base (`0a6948210`, clean detached worktree) and 1,878
at head (`156e3538f`)**.
- **Symbol anchors.** No anchor names `resolveHashShadowKeys`.
`check:adr-symbol-anchors`: 2,658 anchors resolve at both ends.
- **`check:tenant-chokepoint`.** 24 `getBuilder` bindings across 3 files
at both ends, rule 2 clean at both. Rule 2's `SCAN_FILES` names
`sql-driver.ts` and not the seam modules, so it no longer visits the
body's one `.where({ TABLE_SCHEMA, TABLE_NAME })` and one
`.whereIn('COLUMN_NAME', ...)` (catalog filters, no null comparand, no
tenant column); `where`/`whereIn`/`whereRaw`/`raw` call lines in
`sql-driver.ts` go 100 to 98. The verdict and the population the gate
prints are unchanged, so it does not go empty.
- **Logger receivers.** The body does not log.
`check:logger-receiver-detach` exits 0 at both ends.
- **Text readers.** The CLI `*.pin.test.ts` files,
`logger-receiver-detach.test.ts`,
`sql-driver-compile-refusal-seam.test.ts`, the spec liveness test and
the scripts that read `sql-driver.ts` as text match none of
`isHashShadowCarrier`, `parseHashShadowKeyParts`, `HashShadow` or
`shadowKey` (`git grep`: 0 hits).
- `check:driver-conformance` at both ends: **55 covered, 0 in the DEBT
ledger, 0 exempt.**
## Verification
- `tsc --noEmit` (driver-sql) exit 0. `eslint --no-inline-config
packages/drivers/driver-sql/src` exit 0 (driver-sql declares no `lint`
script; the repo-wide `pnpm lint` is CI's).
- Each suite under its own `os-verify-lock` call, exit 0 at every end,
compared per test name and status from vitest's JSON reporter:
- `driver-sql`: first pair 3,999 tests (3,787 passed, 212 skipped; 247
files); merged pair 4,010 (3,796 passed, 214 skipped; 248 files,
#26015's new file). 0 lost, 0 changed, 0 added on each pair.
- `driver-turso` (against that end's built driver-sql `dist`): 2,526
tests (2,492 passed, 34 skipped; 95 files) at every end; 0 / 0 / 0
(2,513 distinct names).
- `driver-sqlite-wasm`: 704 tests (704 passed; 39 files) at every end; 0
/ 0 / 0.
- **Late-binding probe** (scratch, node against the built `dist`, not
committed): 17 readings, **identical at base and head on both pairs**
(`diff` empty). It covered: a direct call with a fake `knex` set on the
instance after construction (the same builder chain,
`information_schema.COLUMNS`, the `database()` read, the carrier columns
in `whereIn`, and the parsed `shadowKey` per carrier, NULL-safe and raw,
plus an unresolved carrier and a plain index left alone); no carrier
(returns without touching `knex`); a synchronous throw in the builder
and an async rejection (both swallowed, resolves `undefined`); a
non-array argument (a rejection with a `TypeError`, never a synchronous
throw, at both ends); a subclass override of `resolveHashShadowKeys`
reached from `introspectIndexes`' MySQL arm (via subclass dialect
getters and a `knex.raw` stub); the real method through that arm; and an
instance spy on it, reached once.
- **Live MySQL-dialect cell**: the four hash-shadow live files (`11627`,
`12998`, `13015`, `15479`) ran against a local MariaDB 10.11 at base
`0a6948210` and merged head `156e3538f`: 31 tests at both ends (12
passed, 18 failed, 1 skipped), **0 status differences**. MariaDB does
not take the shadow path these files assert on (the failures name a
missing shadow column or a missing shadow-path log line, identically at
both ends), so this cell does not reach the moved body; it is MariaDB,
not MySQL 8, and only shows the diff changes nothing there. CI's live
MySQL lane, where it runs, is the authority.
- `dispatch-gates --commands` on this diff at the merged head
`156e3538f` (merge base `0a6948210`, no STALE TREE): 55 derived
commands, each run with its exit captured before any pipe. `--ran`: 55
derived, 54 run, 1 NOT MEASURED, 0 unrun. The NOT MEASURED one is
`check:dual-build-cjs-loads` (exit 3, PREREQUISITE NOT MET: it needs
every package's `dist`), which CI runs. `check-plugin-teardown-shape
--self-test` first exited 3 (shallow clone) and exits 0 after fetching
its positive-control commit; `check:lean-entry-closure` first exited 3
(no `objectql` dist) and exits 0 after building it.
- Also run, outside the derivation: `check:adr-anchors`,
`check:adr-symbol-anchors`, `check:commit-card-trailers` and its
`--range origin/main..HEAD` (2 commits, clean): all exit 0.
- No reverse verification or ablation: the diff changes no tested
behaviour.
## Acceptance notes
- **`check:tenant-chokepoint` rule 2 visits two fewer catalog filters in
`sql-driver.ts`** (above). Widening `SCAN_FILES` to the seam modules is
a gate edit and the open precondition the series carries for the
`getBuilder` areas; it is not made here.
- The class method now returns the moved function's promise instead of
being an `async` method; a caller awaits the same settlement, and a
synchronous throw inside the body still arrives as a rejection (probe
reading above).
- **Proposed next slice** (unchanged from cut 6's report):
`applyIndexDriftOp` and `restoreBareIndexAfterFailedTighten` into
`sql-driver-schema-sync.ts` beside cut 6's pair. Neither builds through
`getBuilder`; screen statics and price at dispatch; `applyIndexDriftOp`
carries the ADR-0120 D4 ceremony, so the anchor entry's D4 paragraph
would need a new entry for that module.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01AuyWbsvLe5peToiMx3LiTd
Co-authored-by: Claude <noreply@anthropic.com>
1 parent d1ea236 commit bd28708
2 files changed
Lines changed: 60 additions & 30 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
31 | 40 | | |
32 | 41 | | |
33 | 42 | | |
| |||
81 | 90 | | |
82 | 91 | | |
83 | 92 | | |
84 | | - | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
85 | 100 | | |
86 | 101 | | |
87 | 102 | | |
| |||
925 | 940 | | |
926 | 941 | | |
927 | 942 | | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
126 | | - | |
127 | 126 | | |
128 | 127 | | |
129 | 128 | | |
| |||
161 | 160 | | |
162 | 161 | | |
163 | 162 | | |
164 | | - | |
165 | | - | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
166 | 166 | | |
167 | 167 | | |
168 | 168 | | |
| |||
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
| 174 | + | |
174 | 175 | | |
175 | 176 | | |
176 | 177 | | |
| |||
15131 | 15132 | | |
15132 | 15133 | | |
15133 | 15134 | | |
15134 | | - | |
| 15135 | + | |
15135 | 15136 | | |
15136 | 15137 | | |
15137 | 15138 | | |
15138 | | - | |
15139 | | - | |
15140 | | - | |
15141 | | - | |
15142 | | - | |
15143 | | - | |
15144 | | - | |
15145 | | - | |
15146 | | - | |
15147 | | - | |
15148 | | - | |
15149 | | - | |
15150 | | - | |
15151 | | - | |
15152 | | - | |
15153 | | - | |
15154 | | - | |
15155 | | - | |
15156 | | - | |
15157 | | - | |
15158 | | - | |
15159 | | - | |
15160 | | - | |
15161 | | - | |
15162 | | - | |
| 15139 | + | |
| 15140 | + | |
| 15141 | + | |
| 15142 | + | |
| 15143 | + | |
| 15144 | + | |
15163 | 15145 | | |
15164 | 15146 | | |
15165 | 15147 | | |
| |||
0 commit comments