Repository navigation
Commit 51cc7f9
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XLmmFpmgAHJChMp7idfTGmz)_
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
Cut 8 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6417688620`; this is the slice cuts 6 and 7
both proposed (Release `6417590425`). The bodies of the protected
`SqlDriver#applyIndexDriftOp` (one index drift op, every dialect) and
`SqlDriver#restoreBareIndexAfterFailedTighten` (the ADR-0120 restore it
runs when a NULL-safe tightening cannot be created after the old index
is gone) move unedited into
`packages/drivers/driver-sql/src/sql-driver-schema-sync.ts`, beside cut
6's `applyDriftOpInPlace` and `rebuildSqliteTablePatched`. They reach
the class through that module's existing host, `SchemaSyncHost`,
**widened by exactly the seven members these two bodies read** and
nothing else. Both methods keep their name, docblock, signature (less
`async`) and position.
The ADR-0120 D4 paragraph of the `sql-driver.ts` anchor entry follows
the apply-side body into a new anchor entry for
`sql-driver-schema-sync.ts` (below). No `docs/adr/**` edit, no
`packages/spec/**` edit, no new gate.
It is move-only, and the card stays open for the later cuts. Branch
`claude/project-thread-wbvc9p` (platform-assigned to this card thread,
as the claim records). One commit, `68fc9470`, on `origin/main`
`a335f1def`.
**Net line count (the seat's rule from ACCEPT `6385306916`).**
`sql-driver.ts` goes from 21,431 lines to 21,334: **-97**. The two
bodies are 122 lines out (105 + 17); the two stubs are 24 lines in (15 +
9); the schema-sync import comment gains one line (+1). The module grows
227 to 372 lines.
**Serial with the file's in-flight PRs.** Re-measured at my start: 32
open PRs, each file list read in full (the two over 100 files paged to
the end: #26138, 343 files, none under `packages/drivers/**`; #25640,
the Version Packages PR, only `CHANGELOG.md` and `package.json` for the
driver packages). None touches `sql-driver.ts`,
`sql-driver-schema-sync.ts` or the driver-sql anchor entries.
## The area, measured on `a335f1def`
- `applyIndexDriftOp` is lines 14776-14882 of `sql-driver.ts` (105 body
lines); `restoreBareIndexAfterFailedTighten` is lines 14893-14914 (17
body lines). Callers: `applyMigrationEntries` (class) and cut 6's
`applyDriftOpInPlace` body (module, through its host closure) call
`applyIndexDriftOp`; only `applyIndexDriftOp`'s body calls the restore.
- Both are protected with annotated return types (a promise of boolean,
a promise of void), so the inferred-return limit does not bite.
- Neither builds through `getBuilder` (the only knex use is
`this.knex(op.table).columnInfo()`), so `check:tenant-chokepoint` rule 1
is untouched, and neither has a `.raw(` / `.where(` site, so rule 2
visits exactly what it visited.
- No static read and no cast-wrapped `this` read. The `this` reads are
`knex`, `logger`, `syncDeclaredIndexes`, `getExistingIndexNames`,
`dropIndexIfExists`, `dropOrphanedHashShadowColumn`,
`probeNullSafeUniqueDuplicates`, `logDurabilityFailure` and
`restoreBareIndexAfterFailedTighten` (the restore reads four of those).
No `this.FIELD.delete/insert/update(` site, so `UNTYPED_RECEIVERS` does
not move.
- `TursoDriver` and `SqliteWasmDriver` override neither
(`turso-driver.ts` names `applyIndexDriftOp` once, in a comment). One
test subclass calls `applyIndexDriftOp` through `this`
(`sql-driver-13056-orphan-shadow-column-cleanup.test.ts`), which still
reaches the class method. No script, doc or ADR names either method by
path.
## The shape (#23050 shape B, as cuts 1-7 apply it)
- Each class method keeps its docblock and signature, byte-identical
less `async`. Its body is one host literal plus `NAME.call(host, ...)`,
marked `[#25521 cut 8]`, and it returns the moved function's own
promise.
- `knex` and `logger` go as GETTERS that read the driver at call time;
the seven methods go as closures that call the method on the driver at
call time. So a subclass override, an instance spy, or a `knex`/`logger`
replaced after construction is still the one the body reaches (probe
below).
- Each moved function types its `this` as the `Pick` of `SchemaSyncHost`
over the members it reads, and each stub annotates its literal as the
`ThisParameterType` of the moved function. No cast, and no member
becomes public.
- `SchemaSyncHost` gains `dropIndexIfExists`,
`dropOrphanedHashShadowColumn`, `getExistingIndexNames`,
`logDurabilityFailure`, `probeNullSafeUniqueDuplicates`,
`restoreBareIndexAfterFailedTighten` and `syncDeclaredIndexes`, each
typed as the class member's indexed access, in the interface's
alphabetical order. `knex`, `logger` and `applyIndexDriftOp` were
already there.
- **Module-level declarations.** The bodies read only the `DriftOp`
type, which the module already imports from `schema-drift.ts`. No
declaration gains an `export`; `index.ts` re-exports nothing from the
module, and `sql-driver.ts` drops no import.
- The module header gains a `[#25521 cut 8]` paragraph; the
`sql-driver.ts` import comment names cut 8.
- The move was produced by a script from the source text, not retyped:
each body line re-indented two columns.
## The ADR anchor follows the body
`check:adr-anchors` counts decision-letter citations on the anchored
surface (each anchor's `invariant` plus the full text of each anchored
file). The moved bodies carry three `ADR-0120 D4` citations (the
ceremony comment and the refusal text in `applyIndexDriftOp`, the
restore's error text); the restore's docblock citation stays on the
class.
-
`scripts/adr-anchors/packages__drivers__driver-sql__src__sql-driver.ts.json`:
the `ADR-0120 D4: …` sentences leave its `invariant` and `ADR-0120`
leaves its `adrs`. The `ADR-0053` paragraph is untouched.
- New
`scripts/adr-anchors/packages__drivers__driver-sql__src__sql-driver-schema-sync.ts.json`:
`adrs: ["ADR-0120"]`, and its `invariant` is those D4 sentences,
byte-identical.
- Count: **1879 decision-letter citations at base `a335f1def` and at
head `68fc9470`**; anchored files 88 to 89; both runs exit 0.
- What stays in `sql-driver.ts`: the plan-side duplicate pre-flight
(`applyNullSafeUniquePreflight`, `probeNullSafeUniqueDuplicates`) and
the `GLOBAL_TENANT` key fold, which that paragraph also describes. The
file still cites `ADR-0120` on 29 lines (10 of them `ADR-0120 D4`), but
no anchor entry names it for ADR-0120 any more. Raised to the seat in
the report as an open question; this PR follows the claim's wording.
## The published `.d.ts` does not change
Under the series bar (ruling `6348891160`, letter A). Each end built
with `pnpm turbo run build --filter=@objectstack/driver-sql` against the
same dependency tree; the base leg restores the base text of the two
source files in this worktree after the commit, 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`; the two
are identical at both ends.
- Raw sha256 of both files at base and at head:
`5028e040e1501b0bd72b91fafcf4e1cb372393c59baa5bab8b936b240dd2d3f5` (cut
7's hash), `cmp` identical.
- Positive control: the head `index.d.ts` with `protected` dropped from
`applyIndexDriftOp` (line 5606) hashes to
`e5e7a31c2fd4231d94f0a95af3c6e7e7b49225b6c1538a86528e7c9bc20fefa7`, a
4-line diff, `cmp` exit 1.
- Export lists (CJS `require` and ESM `import` of the built dist): 56 /
56 names at both ends, identical.
- The head dist carries the move: `.call(host` sites in `index.mjs` 19
at base, 21 at head.
## Move-only proof
TypeScript compiler AST leaf tokens (JSDoc nodes skipped), base
`a335f1def` against head `68fc9470`, scratch script, not committed:
- `applyIndexDriftOp`: body 502 tokens, 0 differ; 46 comments identical;
parameters less `this` 3 tokens, 0 differ; return type 4 tokens, 0
differ; `async` on both; 107 body lines, each the base line less two
leading spaces.
- `restoreBareIndexAfterFailedTighten`: body 132 tokens, 0 differ; 1
comment identical; parameters less `this` 15 tokens, 0 differ; return
type 4 tokens, 0 differ; `async` on both; 19 body lines, each the base
line less two leading spaces.
- Both stubs: leading trivia (docblock) and signature identical to base
less `async`.
- Class: 348 to 348 members in the same order; the 346 unmoved members
byte-identical (full text with trivia).
- `sql-driver.ts` top level: 207 to 207 statements, 205 byte-identical;
the two that differ are the schema-sync import (with its comment) and
the class.
- `sql-driver-schema-sync.ts`: the 5 base statements become 7; 3
byte-identical, the 2 that differ are the import carrying the module
header and `SchemaSyncHost`; the 2 new ones are the moved functions.
- Result `PROOF OK`, exit 0. Negative control (`REFUSING to rebuild` to
`REFUSING to rebui1d` in a module copy): 1 token and 1 line differ,
`PROOF FAILED`, exit 1.
## Tests
Each suite under its own `os-verify-lock` hold, vitest JSON compared per
test name and status, base `a335f1def` against head `68fc9470`:
| Suite | Base | Head | Lost / changed / added |
|:--|:--|:--|:--|
| `@objectstack/driver-sql` | 4010 (3796 passed, 214 skipped; 248 files)
| 4010 (3796 passed, 214 skipped; 248 files) | 0 / 0 / 0 |
| `@objectstack/driver-turso` (against that end's built driver-sql dist)
| 2526 (2492 passed, 34 skipped; 95 files) | same | 0 / 0 / 0 |
| `@objectstack/driver-sqlite-wasm` | 704 (704 passed; 39 files) | same
| 0 / 0 / 0 |
- `pnpm exec tsc --noEmit` in driver-sql: exit 0. `pnpm exec eslint
--no-inline-config packages/drivers/driver-sql/src`: exit 0, 268 files,
0 errors, 0 warnings.
- **Late-binding probe** (scratch, node against each end's built dist on
in-memory SQLite, not committed): 13 readings, base and head output
identical (`diff` empty). It covers the `unbuildable_index` early return
with no `knex` read; `create_index` through a `knex` replaced on the
instance after construction; `replace_unique_index` both ways, the
skipped create warning on a `logger` replaced after construction;
`recreate_index` refused over duplicates through an instance spy on
`logDurabilityFailure`, applied on clean data, its create throwing (an
instance spy on the restore reached with the cause, the restore's error
logged, the rejection rethrown) and its create silently absent (a
subclass override of the restore reached with an undefined cause); the
restore whose own re-create fails (the NOT enforced message, the cause
passed as meta); `drop_index` running the index half before the shadow
half; a `null` op answering a `TypeError` rejection, never a synchronous
throw, from both methods; and the `default` arm.
- No ablation: no tested behaviour changed. `test:repo` not run locally
(the diff touches no repo-project test; CI's Test Core runs it).
## Gates
Local, head `68fc9470`.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (change set vs merge base `a335f1def`, 4
paths): 65 commands, each exit captured before any pipe. 62 exit 0 on
the first run. `check-plugin-teardown-shape.mjs --self-test` exit 3
(shallow clone) then exit 0 after `git fetch origin 621a487` (its
positive control). `check:lean-entry-closure` exit 3 (no objectql dist)
then exit 0 after `pnpm turbo run build --filter=@objectstack/objectql`
under the lock. `check:dual-build-cjs-loads` exit 3, PREREQUISITE NOT
MET (needs every package's dist): NOT MEASURED locally, CI runs it.
- `--ran`: "65 derived famil(ies) accounted for — 64 run, 1 NOT-MEASURED
(1 DERIVED from a recorded exit 3)", exit 0.
- Card-named, base read in a clean detached worktree at `a335f1def` and
head at `68fc9470`, exit 0 at both ends:
- `check:adr-anchors`: 88 to 89 anchored files; **1879 decision-letter
citations at base and at head**.
- `check:adr-symbol-anchors`: 2658 anchors resolve at both.
- `check:tenant-chokepoint`: 24 `getBuilder()` bindings across 3 files
at both; rule 2 clean at both.
- `check:logger-receiver-detach`: 0 detaches at both (3731 non-test TS
files walked at base, 3732 at head, where the base worktree lacks the
gitignored generated spec registry; the `logger` getter keeps the
receiver).
- `check:driver-conformance`: 55 covered, 0 DEBT, 0 exempt at both.
- `node scripts/check-tenant-audit-census.mjs`: 243 write call sites
certified, every `UNTYPED_RECEIVERS` row matched, at both.
- Also exit 0: `check:nul-bytes`, `check:commit-card-trailers`.
`check-platform-checklist --changed-from` not owed (no exported symbol
renamed or deleted).
- `origin/main` moved 9 commits (to `d00215f68`) while this ran; none
touches `packages/drivers/**`, `scripts/adr-anchors/**` or
`check-adr-anchors.mjs`, `git merge-tree` against it is clean, and
`dispatch-gates --commands` derives the same 65-command list there. Not
merged: CI tests the merge ref.
## Acceptance notes
- The ADR-0120 anchor for `sql-driver.ts` is gone with this cut (see
above); the residual plan-side mechanism there is named in the report's
`open_questions` for the seat.
- Proposed next slice: none measured in this cut. The card's remaining
`SqlDriver` areas are the seat's to pick.
`skip-changeset`: move-only, nothing a published package ships changes
(the `.d.ts` is byte-identical; the emitted JS runs the same bodies
through the host).
---
_Generated by [Claude
Code](https://claude.ai/code/session_0155UnTppT9uLobphwpxhiZu)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6b93552 commit 51cc7f9
4 files changed
Lines changed: 183 additions & 129 deletions
File tree
- packages/drivers/driver-sql/src
- scripts/adr-anchors
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
12 | 20 | | |
13 | 21 | | |
14 | 22 | | |
| |||
54 | 62 | | |
55 | 63 | | |
56 | 64 | | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
57 | 68 | | |
58 | 69 | | |
59 | 70 | | |
60 | 71 | | |
| 72 | + | |
61 | 73 | | |
62 | 74 | | |
63 | 75 | | |
64 | 76 | | |
| 77 | + | |
65 | 78 | | |
| 79 | + | |
| 80 | + | |
66 | 81 | | |
67 | 82 | | |
68 | 83 | | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
69 | 214 | | |
70 | 215 | | |
71 | 216 | | |
| |||
0 commit comments