Repository navigation
Commit 9407318
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DRkza71oHtDYy29jXfxjhrY)_
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
Cut 5 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6408067063`. The body of the protected
`SqlDriver#introspectIndexes` moves unedited into cut 1's module,
`packages/drivers/driver-sql/src/sql-driver-introspection.ts`, and
reaches the class through cut 1's host, `IntrospectionHost`, which gains
one member. The method keeps its name, docblock, signature (less
`async`) and position. `resolveHashShadowKeys`, the one class method the
body calls, stays in the class with the rest of the hash-shadow family.
It is move-only, and the card stays open for the later cuts. Branch
`claude/project-thread-8aooxu` (platform-assigned to this card thread,
as the claim records), cut from `origin/main` at `f00e8d5c8` (cut 4
merged as `b1790841b` before it).
**Net line count (the seat's rule from ACCEPT `6385306916`).**
`sql-driver.ts` goes from 21,595 lines at base to 21,512 at head:
**-83** (cut 4 priced it at about -82). `sql-driver-introspection.ts`
goes from 800 to 927 lines.
**Serial with the file's in-flight PRs.** At claim the seat read no open
PR touching `sql-driver.ts` (hot-file queue on seat post #20966: this is
the one slice in flight). Re-measured just before this PR was opened: 8
open PRs, each file list read in full. None touches
`packages/drivers/driver-sql/**`, `driver-turso/**` or
`driver-sqlite-wasm/**`, except the Version Packages PR #25640, which
touches only those packages' `CHANGELOG.md` and `package.json`.
`origin/main` moved one commit past the base meanwhile (#25904, now
`2a728ba2a`). It touches no driver package and no gate script this diff
derives, and it merges clean, so `main` is not merged in.
## The area, re-measured at `f00e8d5c8`
- `introspectIndexes` with its docblock is lines 15096-15250 of
`sql-driver.ts` (155 lines; the method itself 15143-15250). `git blame`
with `--since` 30 days before the base attributes **0** of those lines
to the last 30 days; the file has 63 commits in that window (the clone's
history was deepened to 2026-09-20, before the window opens, for the
reading).
- It is protected, and its return type is annotated (a promise of
`PhysicalIndex[]`), so the inferred-return limit does not bite.
- It does not build through `getBuilder` (`check:tenant-chokepoint` rule
1: 24 bindings across 3 files at both ends).
- It reads no static: the fields and getters it reads are `knex`,
`isMysql`, `isPostgres` and `isSqlite`, all already `IntrospectionHost`
members, plus the method `resolveHashShadowKeys`.
- It has no `this.FIELD.delete/insert/update(` site: its `.set(` /
`.get(` / `.push(` calls are on a local `Map` and local arrays.
- `insertOnlyUpsertColumns` is not touched (#8740).
## The shape (#23050 shape B, as cuts 1-4 apply it)
- The class keeps `introspectIndexes`, docblock and parameter JSDoc
included, byte-identical except that `async` is dropped. Its body is now
one host literal plus `introspectIndexes.call(host, tableName, opts)`,
marked `[#25521 cut 5]`. It returns the moved function's own promise, so
a caller awaits the same settlement.
- `IntrospectionHost` gains one member, `resolveHashShadowKeys`, typed
as the class member (an indexed access on `SqlDriver`). Its ten existing
member lines are unchanged. The moved function types its `this` as the
`Pick` of the host over exactly the five members its body reads, and the
stub annotates its literal as the `ThisParameterType` of the moved
function. There is no cast, and no member becomes public.
- `knex` and the three dialect getters go as GETTERS that read the
driver at call time. `resolveHashShadowKeys` goes as a late-bound
closure that calls it on the driver, so a subclass override or an
instance spy is still the one the body reaches.
- **Why `resolveHashShadowKeys` stays.** The claim's surface allows the
helpers only `introspectIndexes` calls, and it is one of them (its only
caller). But the series carries "protected statics keep the hash-shadow
family in the class" (cut 4's release `6388161035`), and cut 4's
proposal for this cut kept it too, so it is left for the seat to price
as its own slice (see the acceptance notes).
- **Module-level declarations.** The body reads `parseIndexDdl`,
`applyIndexKeyParts` and the type `PhysicalIndex`. All three live in
`schema-drift.ts`, which exports them, so the module imports them from
there (not a copy). After the move `sql-driver.ts` no longer reads the
two functions, so they leave its `./schema-drift.js` import list;
`PhysicalIndex` stays there, other members still read it. No declaration
gains an `export`. `index.ts` re-exports nothing from this module.
- The move was produced by a script from the source text, not retyped:
the parameter list, return type and body lines, re-indented two columns,
except the 9 lines that continue one of the body's two multi-line SQL
template literals. Those keep their bytes (cut 1's rule: there the
indentation is statement text).
- Cut 1's module header gains a `[#25521 cut 5]` paragraph, and the
import comment in `sql-driver.ts` is re-worded to name
`introspectIndexes`. Both are comment-only.
### Overrides and spies, measured
- `TursoDriver` overrides `introspectIndexes` and calls
`super.introspectIndexes(tableName, opts)` on its local arm. The class
method is still there and hands the body its host.
- `SqliteWasmDriver` overrides the getter `isSqlite`. The host reads it
through a getter that reads the driver.
- `sql-driver-12732-varchar-emitter-parity-wiring.test.ts` spies on
`introspectIndexes` on the instance; that is still the class method.
- A scratch probe against the built `dist` (not committed) gave 18
readings, **identical at base and at head** (diff empty). It covered:
the SQLite answer for a table with a primary key, a composite UNIQUE
constraint, a plain index, a partial unique index and an expression
index (columns, `partial`, `expressions`, `nullSafeColumns`);
`getExistingIndexNames`; a missing table; a failing `PRAGMA index_info`
under the default (rejects) and under `onFailure: 'partial'` (the short
list); a `knex.raw` that throws synchronously (the method still returns
a promise that rejects, at both ends); a subclass `introspectIndexes`
that calls `super`; the MySQL arm through a subclass overriding the
three dialect getters, with the `EXPRESSION` fallback statement; a
subclass override of `resolveHashShadowKeys` and then an instance
assignment of it (both reached); a rejecting `resolveHashShadowKeys`
(surfaces by default, swallowed under `partial`); and a subclass
`isSqlite` getter flipped between two calls (read at call time).
## The published `.d.ts` does not change
Under the series bar (ruling `6348891160`, letter A), measured on base
`f00e8d5c8` and head `bd1670fe0`, each built with `pnpm --filter
@objectstack/driver-sql build` against the same dependency tree (the
base leg restores the two base files into this worktree after the cut
commit, rebuilds, reads, then restores HEAD, proved by blob hash and an
empty `git diff HEAD`).
- This package emits `dist/index.d.ts` and `dist/index.d.mts` (no
`.d.cts`); the two are identical at both ends.
- Raw sha256 of both files, base and head, all four the same:
`93da45168e82136b7613944525e47402d5dc6f9f8daa9efa4bdceeaa11b52a89` (cuts
1-4's hash, unchanged). `cmp` base vs head: identical, raw diff 0 lines,
so the proof rests on raw identity and no normaliser is relied on.
- Positive control on a copy of the head `dist/index.d.ts`: line 5714,
`protected introspectIndexes(tableName: string, opts?: {`, with
`protected` removed, gives
`cbaacf3c70282bd8dfc867c2f97d0f218b114c06b7fc11fbde5b03f5c05f9da0` and a
4-line diff.
- Export tables: the ESM and CJS bundles each export the same 56 names
at base and head. The sorted list hashes to
`d61a9dd3a02661602b1bb2dbe18152ac43986148f36b2746f40c0884bd8ffdec` on
all four (cut 4's value).
- The head build carries the move: `dist/index.mjs` 29 to 30 host
`.call(` sites, `dist/index.js` 30 to 31.
No changeset: `skip-changeset`, per ruling `6348891160` item 4.
## Proof of move-only
- **Body, by AST token** (recursive `getChildren` leaves, template
pieces as their exact source text, comments and JSDoc compared line by
line less leading whitespace). The moved function's parameters (less the
added `this`), return type and body have the same token sequence as the
base method, and `async` matches. 673 body tokens compared, 0 differ; 2
parameters identical; return type identical.
- **Lines**: 98 body lines compared. 88 are the base line with two
leading spaces removed, 9 are byte-identical template-literal
continuation lines, 0 other.
- **Negative control**: in a copy of the module, `type = 'index'`
becomes `type = 'indx'` inside the SQLite arm's `sqlite_master` template
literal. The check then reports 1 token and 1 line different and exits
`PROOF FAILED`, exit 1.
- **Class side**: 347 members at base and head. The 346 that did not
move are byte-identical to base, leading trivia included.
- **Top level of `sql-driver.ts`**: 202 non-class statements at base and
head; 200 byte-identical. The two others are the `./schema-drift.js`
import (loses exactly `applyIndexKeyParts` and `parseIndexDdl`) and the
`./sql-driver-introspection.js` import (gains exactly
`introspectIndexes`; its leading comment re-worded).
- **The module**: 9 statements at base, 11 at head. The 8 base
statements other than `IntrospectionHost` are byte-identical at head
(the first carries the re-worded header as leading trivia).
`IntrospectionHost` keeps its ten member lines and gains one. The two
new statements are the `./schema-drift.js` import and the moved
function.
- **Size**: +143 / -99 over 2 files, far under the 3,000-line
manual-merge line.
## 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 (`formatOutput`, `presentReadValue`) and ADR-0120 D4
(the `recreate_index` ceremony). Neither paragraph describes the moved
body, so per card ask 3 no entry is owed. The moved body cites no ADR;
the docblock's ADR-0048 mention stays on the class. `check:adr-anchors`:
85 anchored files at both ends; decision-letter citations on the
anchored surface **1,847 at base and 1,847 at head**.
- **Symbol anchors.** No ADR, checklist or doc anchors
`sql-driver.ts#introspectIndexes` (`git grep` over `docs/`, `content/`,
`scripts/`, `.github/`: 0 hits). `check:adr-symbol-anchors`: 2,474
anchors resolve at both ends.
- **`check:tenant-chokepoint`.** Rule 1 verdict and population unchanged
(above). Rule 2 visits raw-family calls in `SCAN_FILES`; the moved
body's five `knex.raw(` call sites (`sqlite_master`, `PRAGMA
index_list`, `PRAGMA index_info`, `pg_index`, MySQL `STATISTICS`) are
catalog reads, none says `IS NULL` against a tenant column (the
`pg_index` read says `ix.indpred IS NOT NULL`, not a tenant column).
Verdict unchanged; `.raw(` call sites in `sql-driver.ts` go 75 to 70
(see the acceptance notes).
- **Logger receivers.** The moved text reads no logger.
`check:logger-receiver-detach`: 0 detaches at both ends.
- **Doc comments** that name `SqlDriver.introspectIndexes`
(`schema-drift.ts`, `turso-driver.ts`,
`packages/spec/src/contracts/schema-diff-service.ts`) and the `{@link
introspectIndexes}` references in the class still point at the method,
which is still there.
- `check:driver-conformance` at base and head: **55 covered, 0 in the
DEBT ledger, 0 exempt, both times.**
## Verification
- `tsc --noEmit` (driver-sql) exit 0. `eslint --no-inline-config` over
`packages/drivers/driver-sql/src` (265 files, the module included): 0
errors, 0 warnings. Repo-wide `pnpm lint` (the seat asked for it;
driver-sql declares no lint script): exit 0 at head `bd1670fe0`.
- `packages/drivers/driver-sql` suite: base 3,999 tests (3,787 passed, 0
failed, 212 skipped; 247 files), head the same. Compared per test name
and status from vitest's JSON reporter: 0 lost, 0 changed, 0 added.
- `packages/drivers/driver-turso` suite, against the rebuilt driver-sql
`dist` at each end: base 2,526 tests (2,492 passed, 0 failed, 34
skipped; 95 files), head the same; per name 0 / 0 / 0 (2,513 distinct
names, 13 repeat).
- `packages/drivers/driver-sqlite-wasm` suite: base 704 tests (704
passed; 39 files), head the same; per name 0 / 0 / 0.
- Each suite ran under its own `os-verify-lock` call, `VERDICT
command-exit 0` at both ends.
- `dispatch-gates --commands` on this diff, at head `bd1670fe0`: 55
derived commands, each run with its exit code captured before any pipe.
`--ran` reconciles 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:lean-entry-closure` first exited 3 (no `objectql` dist) and exits
0 after `turbo run build --filter=@objectstack/objectql`;
`check-plugin-teardown-shape --self-test` first exited 3 on the shallow
clone and exits 0 after `git fetch --unshallow`.
- `check:commit-card-trailers --range origin/main..HEAD`: 1 commit,
clean.
- No reverse verification or ablation: the diff changes no tested
behaviour.
## Acceptance notes
- **`check:tenant-chokepoint` rule 2 reads 5 fewer raw call sites in
`sql-driver.ts`.** `SCAN_FILES` names `sql-driver.ts` and not the seam
modules, so rule 2 no longer visits the five catalog `knex.raw(` calls
that moved; the module now holds 24 `.raw(` sites. None is an arm on a
tenant column today, but a future edit that added one in the module
would not be caught by rule 2. Widening `SCAN_FILES` is a gate edit and
the open precondition the series carries for the `getBuilder` areas; it
is not made here.
- **`resolveHashShadowKeys` could follow.** Its only caller is now the
moved body, its body reads only `knex` and two `schema-drift.ts`
functions (no static), and its body (about 29 lines) is longer than the
stub it would need (about 7), so it would pass the net-line rule at
roughly -22. It stays because the series keeps the hash-shadow family in
the class; whether it moves is the seat's call.
- **Proposed cut 6** (cut 4's next candidate, re-read here): the SQLite
rebuild pair `applyDriftOpInPlace` (14860) and
`rebuildSqliteTablePatched` (14954), Schema sync. Neither builds through
`getBuilder` and neither has a `this.FIELD.delete/insert/update(` site.
Between them they read `knex` (14 times), `logger` (twice, so
`check:logger-receiver-detach` is the gate to watch on a host getter),
`dialectName`, `isMysql`, `isPostgres`, and the methods
`introspectColumns`, `syncTableIndexes`, `resolveTenantField`,
`nowColumnDefault`, `buildRebuiltColumn`, `applyIndexDriftOp`,
`applyDeclaredColumnDefault`, plus the fields `managedObjectIndexes` and
`managedObjectFields`. That is a wide host; it should be priced against
the net-line rule at its dispatch.
- `TursoDriver`'s `introspectIndexes` override still calls
`super.introspectIndexes(tableName, opts)`. That now returns the moved
function's promise instead of an `async` method's promise. A caller
awaits the same settlement, and a synchronous throw inside the body
still arrives as a rejection (probe reading 6).
- Lines that continue a SQL template literal keep their base indentation
inside the module, so they sit two columns deeper than the code around
them (cut 1's rule).
---
_Generated by [Claude
Code](https://claude.ai/code/session_013Wyp3j7s8XDQmCUaKPbmXH)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1d2a246 commit 9407318
2 files changed
Lines changed: 143 additions & 99 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
17 | 31 | | |
18 | 32 | | |
19 | 33 | | |
| |||
67 | 81 | | |
68 | 82 | | |
69 | 83 | | |
| 84 | + | |
70 | 85 | | |
71 | 86 | | |
72 | 87 | | |
| |||
87 | 102 | | |
88 | 103 | | |
89 | 104 | | |
| 105 | + | |
90 | 106 | | |
91 | 107 | | |
92 | 108 | | |
| |||
798 | 814 | | |
799 | 815 | | |
800 | 816 | | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
112 | | - | |
113 | 112 | | |
114 | 113 | | |
115 | 114 | | |
| |||
132 | 131 | | |
133 | 132 | | |
134 | 133 | | |
135 | | - | |
136 | 134 | | |
137 | 135 | | |
138 | 136 | | |
| |||
161 | 159 | | |
162 | 160 | | |
163 | 161 | | |
164 | | - | |
| 162 | + | |
| 163 | + | |
165 | 164 | | |
166 | 165 | | |
167 | 166 | | |
168 | 167 | | |
169 | 168 | | |
| 169 | + | |
170 | 170 | | |
171 | 171 | | |
172 | 172 | | |
| |||
15140 | 15140 | | |
15141 | 15141 | | |
15142 | 15142 | | |
15143 | | - | |
| 15143 | + | |
15144 | 15144 | | |
15145 | 15145 | | |
15146 | 15146 | | |
| |||
15151 | 15151 | | |
15152 | 15152 | | |
15153 | 15153 | | |
15154 | | - | |
15155 | | - | |
15156 | | - | |
15157 | | - | |
15158 | | - | |
| 15154 | + | |
| 15155 | + | |
| 15156 | + | |
| 15157 | + | |
| 15158 | + | |
| 15159 | + | |
| 15160 | + | |
| 15161 | + | |
| 15162 | + | |
| 15163 | + | |
| 15164 | + | |
15159 | 15165 | | |
15160 | | - | |
15161 | | - | |
15162 | | - | |
15163 | | - | |
15164 | | - | |
15165 | | - | |
15166 | | - | |
15167 | | - | |
15168 | | - | |
15169 | | - | |
15170 | | - | |
15171 | | - | |
15172 | | - | |
15173 | | - | |
15174 | | - | |
15175 | | - | |
15176 | | - | |
15177 | | - | |
15178 | | - | |
15179 | | - | |
15180 | | - | |
15181 | | - | |
15182 | | - | |
15183 | | - | |
15184 | | - | |
15185 | | - | |
15186 | | - | |
15187 | | - | |
15188 | | - | |
15189 | | - | |
15190 | | - | |
15191 | | - | |
15192 | | - | |
15193 | | - | |
15194 | | - | |
15195 | | - | |
15196 | | - | |
15197 | | - | |
15198 | | - | |
15199 | | - | |
15200 | | - | |
15201 | | - | |
15202 | | - | |
15203 | | - | |
15204 | | - | |
15205 | | - | |
15206 | | - | |
15207 | | - | |
15208 | | - | |
15209 | | - | |
15210 | | - | |
15211 | | - | |
15212 | | - | |
15213 | | - | |
15214 | | - | |
15215 | | - | |
15216 | | - | |
15217 | | - | |
15218 | | - | |
15219 | | - | |
15220 | | - | |
15221 | | - | |
15222 | | - | |
15223 | | - | |
15224 | | - | |
15225 | | - | |
15226 | | - | |
15227 | | - | |
15228 | | - | |
15229 | | - | |
15230 | | - | |
15231 | | - | |
15232 | | - | |
15233 | | - | |
15234 | | - | |
15235 | | - | |
15236 | | - | |
15237 | | - | |
15238 | | - | |
15239 | | - | |
15240 | | - | |
15241 | | - | |
15242 | | - | |
15243 | | - | |
15244 | | - | |
15245 | | - | |
15246 | | - | |
15247 | | - | |
15248 | | - | |
15249 | | - | |
| 15166 | + | |
15250 | 15167 | | |
15251 | 15168 | | |
15252 | 15169 | | |
| |||
0 commit comments