Repository navigation
Commit ab112ea
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XCodTCKnBimkFG3aNs3HsTc)_
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
Cut 9 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6420465502`. Cut 8 measured no next slice,
so this cut opens with a fresh seam table (below) and takes the area it
prices best that breaks no series limit. The bodies of three protected
`SqlDriver` methods move unedited into the existing seam module
`packages/drivers/driver-sql/src/sql-driver-schema-sync.ts`, through its
existing host `SchemaSyncHost`:
- `applyNullSafeUniquePreflight`, the plan-side duplicate pre-flight
that clears or blocks a unique index op;
- `syncDeclaredIndexes`, which materializes a table's declared indexes;
- `createNullSafeUniqueIndex`, the raw DDL for an organization-scoped
unique's expression key.
The module-level helper `formatDuplicateGroups` moves with them,
byte-identical with its docblock. Its only two callers are the
pre-flight and the sync, so it stays module-local and unexported, as its
docblock requires.
These bodies are the rest of the ADR-0120 tightening machinery. Cut 8
already moved its apply side and put the ADR-0120 D4 anchor paragraph on
this module's entry. That paragraph describes the duplicate pre-flight,
which now lives in the module the paragraph anchors. No anchor entry
changes, there is no `docs/adr/**` edit and no `packages/spec/**` edit,
and there is no new gate.
The change is move-only, and the card stays open for later cuts. Branch
`claude/project-thread-k34erv` (the platform assigned it to this card
thread, as the claim records). One commit, `b2b00ab42`, on `origin/main`
`e6dfeb08f`.
**Net line count (the seat's rule).** `sql-driver.ts` goes from 21,334
lines to 20,990: **-344**.
- Out: the three bodies, 354 lines (64 + 258 + 32);
`formatDuplicateGroups` with its docblock and the blank line before it,
20 lines; and the `describeMissingIndexColumns` import name, 1 line,
because its last reader was the moved sync body.
- In: the three stubs, 29 lines (7 + 13 + 9), and 2 import-comment
lines.
- The module grows from 372 to 777 lines.
**Serial with the file's in-flight PRs.** I measured this twice: at
start, and again before `pr_create` (41 open PRs). Each time I read
every open PR's file list in full. Two touch
`packages/drivers/driver-sql/**`, and neither touches `src/`: #26203
changes only `tsconfig.json` and #26198 only `package.json`. No PR
touches `sql-driver.ts`, `sql-driver-schema-sync.ts`, `turso-driver.ts`
or the driver-sql anchor entries.
## Seam table, fresh, on `e6dfeb08f`
`origin/main` is at `e6dfeb08f`, after cut 8 (`51cc7f9603`).
- **Size and churn.** `sql-driver.ts` is 21,334 lines. 30-day lines are
`git blame --line-porcelain` lines whose committer time is on or after
2026-09-26T15:16:49Z, 30 days before the base commit. I deepened history
to 2026-09-18 first, and `scripts/pm/git-history.mjs count` proves 68
commits on the file in that window (26 in the last 7 days). In all,
3,206 lines (15.0%) are from the last 30 days.
- **Class shape.** `SqlDriver` spans lines 5532-21259 with 348 members:
252 methods (49 of them public instance methods), 13 getters and 32
statics, all 32 of them private or protected.
- **Inferred return types.** One public member has one: `supports`, in
the class head.
- **How it was measured.** A TypeScript compiler AST script, which
strips casts, parentheses and `!` before it reads `this`.
- **Sections.** These are the class's own banner comments (`// ===`
blocks and `// ──` sub-banners), cut by contiguous line range.
| Lines | Section | First … last member | Lines | 30-day | Methods
(public) | Inferred public | getBuilder sites | Statics
(private/protected) |
|:--|:--|:--|--:|--:|:--|--:|--:|:--|
| 1-5531 | Module preamble | - | 5,531 | 754 | - | - | - | - |
| 5532-7123 | Class head: fields, statics, constructor, capability
getters | `name` … `assertDialectEmits` | 1,592 | 290 | 14 (1) | 1 | 0 |
18 (18) |
| 7124-7555 | Lifecycle | `connect` … `disconnect` | 432 | 155 | 11 (3)
| 0 | 0 | 6 (6) |
| 7556-10260 | CRUD — IDataDriver core | `find` … `delete` | 2,705 | 739
| 43 (7) | 0 | 12 | 0 (0) |
| 10261-10872 | Bulk & Batch Operations | `bulkCreate` … `count` | 612 |
119 | 9 (6) | 0 | 7 | 0 (0) |
| 10873-10969 | Raw Execution | `rawStatementFault` …
`noteRuntimeIndexDdl` | 97 | 28 | 3 (1) | 0 | 0 | 0 (0) |
| 10970-11062 | Transactions | `beginTransaction` …
`rollbackTransaction` | 93 | 46 | 7 (5) | 0 | 0 | 0 (0) |
| 11063-11594 | Aggregation | `aggregate` …
`unresolvableAggregateColumnRefusal` | 532 | 60 | 5 (1) | 0 | 1 | 0 (0)
|
| 11595-11882 | Distinct | `distinct` …
`unresolvableDistinctColumnRefusal` | 288 | 17 | 3 (1) | 0 | 1 | 0 (0) |
| 11883-11998 | Window Functions | `findWithWindowFunctions` …
`findWithWindowFunctions` | 116 | 4 | 1 (1) | 0 | 1 | 0 (0) |
| 11999-12097 | Query Plan Analysis | `explain` … `analyzeQuery` | 99 |
1 | 2 (2) | 0 | 1 | 0 (0) |
| 12098-12156 | Schema Sync (syncSchema / init) | `syncSchema` …
`reclaimSpace` | 59 | 34 | 3 (3) | 0 | 0 | 0 (0) |
| 12157-13898 | Schema Sync › Data-lifecycle rotation (ADR-0057 P2) |
`rotationStateByTable` … `migrateMysqlTimeColumns` | 1,742 | 72 | 26 (4)
| 0 | 0 | 0 (0) |
| 13899-14155 | Schema Sync › Deferred schema DDL | `setDeferredDdl` …
`flushDeferredSchemaDdl` | 257 | 25 | 6 (4) | 0 | 0 | 0 (0) |
| 14156-15533 | Schema Sync › Managed-schema drift & reconcile |
`dialectName` … `createNullSafeUniqueIndex` | 1,378 | 197 | 23 (3) | 0 |
0 | 0 (0) |
| 15534-15585 | Schema Introspection | `listPhysicalColumns` …
`introspectSchema` | 52 | 46 | 2 (2) | 0 | 0 | 0 (0) |
| 15586-15856 | Internal helpers (head: tenancy, misc) | `getKnex` …
`auditMissingTenant` | 271 | 73 | 8 (1) | 0 | 1 | 0 (0) |
| 15857-18109 | Internal helpers › Filter helpers |
`tableNameForBuilder` … `applyFalseConstant` | 2,253 | 250 | 42 (2) | 0
| 0 | 0 (0) |
| 18110-18285 | Internal helpers › Field mapping | `mapSortField` …
`mapAggregateFunc` | 176 | 2 | 6 (0) | 0 | 0 | 0 (0) |
| 18286-18333 | Internal helpers › Window function builder |
`buildWindowFunction` … `buildWindowFunction` | 48 | 26 | 1 (0) | 0 | 0
| 0 (0) |
| 18334-20280 | Internal helpers › Column creation helper |
`nowColumnDefault` … `applyDeclaredColumnDefault` | 1,947 | 92 | 21 (0)
| 0 | 0 | 8 (8) |
| 20281-20578 | Internal helpers › Database helpers | `sqliteFilename` …
`isJsonField` | 298 | 76 | 9 (2) | 0 | 0 | 0 (0) |
| 20579-21055 | Internal helpers › SQLite serialisation | `formatInput`
… `formatOutput` | 477 | 27 | 2 (0) | 0 | 0 | 0 (0) |
| 21056-21259 | Internal helpers › Introspection internals |
`introspectColumnOrder` … `introspectUniqueConstraints` | 204 | 73 | 5
(0) | 0 | 0 | 0 (0) |
| 21260-21334 | After the class | - | 75 | 0 | - | - | - | - |
### Pricing the eligible methods
A method is eligible to move when it meets every condition below. 191 of
the 241 instance methods do.
- Its return type is annotated, or it is not public.
- It has no `getBuilder` site.
- It has no `this.FIELD.delete/insert/update(` site.
- It reads no private or protected static.
- It makes no `super` read and no bare `this` pass.
- It makes no write to `this`.
- It is not `insertOnlyUpsertColumns`.
**The net-line rule.** Each candidate is priced as its stub minus its
body. A stub costs 4 lines, plus 2 for each field or getter read and 1
for each method read.
The highest-priced candidates, and why each one stays or moves:
| Method (section) | Net | Disposition |
|:--|--:|:--|
| `createColumn` (Column creation helper) | -463 | **Stays.** ADR-0113
cites `sql-driver.ts#createColumn` for the NOT NULL mechanism in this
body, so moving it would need a `docs/adr/**` edit. Five `packages/cli`
`generate-*.pin.test.ts` files also slice `protected createColumn(` …
`switch (type)` out of this file's text. |
| `applyFilterCondition` (Filter helpers) | -357 | **Stays.** ADR-0139
cites `sql-driver.ts#applyFilterCondition`, and a governed `.claude/**`
reference names it too. `sql-driver-compile-refusal-seam.test.ts`
enumerates `INVALID_FILTER` builders in this file only. |
| **`syncDeclaredIndexes`** (Managed-schema drift & reconcile) |
**-245** | **Moves (this cut).** |
| `formatOutput` (SQLite serialisation) | -236 | **Stays.** The
`sql-driver.ts` anchor entry's ADR-0053 paragraph describes this body,
ADR-0104 cites `sql-driver.ts#formatOutput`, and the body reads 11
fields. |
| `initObjects` (Rotation) | -195 | **Stays.**
`packages/spec/liveness/object.json` cites `sql-driver.ts#initObjects`,
which would need a spec edit. |
| `formatInput` (SQLite serialisation) | -183 | **Stays.** ADR-0053 and
ADR-0104 cite `sql-driver.ts#formatInput`. |
| `applyCrossFieldComparison` (Filter helpers) | -179 | Not taken here:
it needs a new module, and I did not screen it against the two readers
named above. Proposed below. |
| **`applyNullSafeUniquePreflight`** (Managed-schema drift & reconcile)
| **-57** | **Moves (this cut).** |
| **`createNullSafeUniqueIndex`** (Managed-schema drift & reconcile) |
**-23** | **Moves (this cut).** |
## Why this area
- **It pays the most of any eligible area.** The cut is -344, and the
best eligible single method is -245. No candidate priced above it is
free of a pointer that a spec or ADR edit would have to move.
- **It belongs in an existing module and host.**
`sql-driver-schema-sync.ts` already holds the apply side of the same
mechanism (cut 8's `applyIndexDriftOp`, which calls
`syncDeclaredIndexes` and `probeNullSafeUniqueDuplicates`).
`SchemaSyncHost` already listed 7 of the 10 members these bodies read.
- **No series limit is touched:**
- none of the three bodies builds through `getBuilder`;
- none reads a static;
- none has a `this.FIELD.delete/insert/update(` site;
- none uses `super`, a bare `this` or a cast-wrapped `this`;
- all three are protected, with annotated return types.
- **Subclasses.** `TursoDriver` overrides
`probeNullSafeUniqueDuplicates` and calls `super`. The bodies reach it
through a late-bound closure, so the override is still the one that
runs. No subclass overrides any of the three moved methods.
- **Path readers, screened.** No script, test, doc or ADR names any of
the three by `sql-driver.ts#…` path, and none slices their text out of
`sql-driver.ts`.
- ADR-0005, ADR-0120, `packages/cli/src/commands/generate.ts` and
`driver-turso/src/remote-transport.ts` name
`SqlDriver.syncDeclaredIndexes` in prose. That method is still on the
class, with the same docblock, so the prose still holds.
- The only reader of `formatDuplicateGroups` outside its callers is one
`{@link formatDuplicateGroups}` in the docblock of
`reclaimBetterSqlite3` in `sql-driver.ts`. See Acceptance notes.
- **What stays on purpose.** `probeNullSafeUniqueDuplicates` stays in
the class. Its body reads the module-level `uniqueProbeNotNullClause`,
so moving it would drag a second helper, and Turso's override already
reaches it through the host.
## The shape (#23050 shape B, as cuts 1-8 apply it)
- Each class method keeps its docblock and signature, byte-identical
less `async`. Its body is now one host literal plus `NAME.call(host,
...)`, marked `[#25521 cut 9]`, and it returns the moved function's own
promise.
- `knex`, `logger` and `isMysql` go as GETTERS that read the driver at
call time. The methods go as closures that call the method on the driver
at call time. So a subclass override, an instance spy, or a `knex` or
`logger` replaced after construction is still the one the body reaches
(see the probe below).
- Each moved function types its `this` as the Pick of `SchemaSyncHost`
over exactly the members it reads. Each stub annotates its literal as
the ThisParameterType of the moved function. There is no cast, and no
member becomes public.
- `SchemaSyncHost` gains `createHashShadowUniqueIndex`,
`createNullSafeUniqueIndex` and `explainUnkeyableTextColumn`, each typed
as the class member's indexed access, in the interface's alphabetical
order. The other members these bodies read were already there: `knex`,
`logger`, `isMysql`, `getExistingIndexNames`, `logDurabilityFailure`,
`probeNullSafeUniqueDuplicates` and `resolveTenantField`.
- **Module-level declarations.**
- The module imports `normalizeDeclaredIndex`,
`describeMissingIndexColumns`, `GLOBAL_TENANT` and the type
`DeclaredIndexInput` from `schema-drift.ts`, and
`isUniqueViolationError` from `@objectstack/types`, the modules that
declare them. No `export` was added anywhere.
- `sql-driver.ts` drops only `describeMissingIndexColumns` from its
import, because the moved sync body was its last reader. Everything else
it imported is still read there.
- `index.ts` re-exports nothing from the module, so the published
surface does not move.
- **Comments.** The module header gains a `[#25521 cut 9]` paragraph
that cites no decision letter. The `sql-driver.ts` import comment names
cut 9 in 2 lines.
- **How the move was made.** A script produced it from the source text;
nothing was retyped. Each body line is re-indented two columns. No line
in the moved bodies starts inside template-literal text, so no line
keeps its base indentation.
## ADR anchors
`check:adr-anchors` counts decision-letter citations on the anchored
surface: each anchor's `invariant`, plus the full text of each anchored
file.
- **Both files are anchored.** `sql-driver.ts` has its ADR-0053 entry,
and `sql-driver-schema-sync.ts` has the ADR-0120 entry cut 8 created.
- **The citations move between anchored files.** The moved bodies carry
their `ADR-0120 D3` and `ADR-0120 D4` citations from one anchored file
to the other, and the new header paragraph cites no letter.
- **The count.** It is **1883 decision-letter citations at base
`e6dfeb08f` and at head `b2b00ab42`**, over 90 anchored files at both
ends. Both runs exit 0.
- **No entry needs a new home.** The only paragraph that describes a
moved body is the ADR-0120 D4 sentence on the duplicate pre-flight, and
it already lives on `sql-driver-schema-sync.ts`'s entry. The ADR-0053
paragraph on `sql-driver.ts` describes `formatOutput` and
`presentReadValue`, and neither moved.
## The published `.d.ts` does not change
This is measured under the series bar (ruling `6348891160`, item 1).
- **How each end was built.** I built each end with `pnpm turbo run
build --filter=@objectstack/driver-sql --force`, 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. The restore is proved by the HEAD blob hashes
(`dbe720a2`, `86929118`), an empty `git diff HEAD` and 0 status entries.
- **The hashes.** The raw sha256 of `dist/index.d.ts` and
`dist/index.d.mts` is the same at base and at head:
`5028e040e1501b0bd72b91fafcf4e1cb372393c59baa5bab8b936b240dd2d3f5` (cut
8's hash). `cmp` finds them identical.
- **Positive control.** I dropped `protected` from `syncDeclaredIndexes`
in the head `index.d.ts`. The result hashes to
`f6a003a07258bfdcd858e4e68504f0960aa01bd85e6e9d4ab387fb26dfa81a2c`, with
a 4-line diff and `cmp` exit 1.
- **Export lists.** CJS `require` and ESM `import` of the built dist
give 56 / 56 names at both ends, identical.
- **The head dist carries the move.** `.call(host` sites in `index.mjs`
go from 21 at base to 24 at head.
## Move-only proof
The proof compares TypeScript compiler AST leaf tokens (JSDoc nodes
skipped), base `e6dfeb08f` against head `b2b00ab42`. It is a scratch
script and is not committed.
| Moved body | Body tokens | Comments | Parameters less `this` | Return
type | Body lines |
|:--|--:|--:|--:|--:|--:|
| `applyNullSafeUniquePreflight` | 316 | 14 | 5 | 4 | 66 |
| `syncDeclaredIndexes` | 806 | 118 | 29 | 4 | 260 |
| `createNullSafeUniqueIndex` | 212 | 8 | 17 | 4 | 34 |
- **Each moved body.** In every row, 0 tokens differ and every comment
is identical. `async` is on both ends, and there are no type parameters.
Each body line is the base line less two leading spaces.
- **The three stubs.** Leading trivia (the docblock) and the signature
are identical to base, less `async`.
- **`formatDuplicateGroups`.** Its 19 lines with the docblock are
byte-identical, it is gone from `sql-driver.ts`, and it is still
unexported.
- **The class.** It has 348 members at both ends, in the same order, and
the 345 unmoved members are byte-identical, trivia included.
- **`sql-driver.ts` top level.** It goes from 207 to 206 statements. The
only base statements that differ are the two imports, the moved helper
and the class.
- **`sql-driver-schema-sync.ts`.** It goes from 7 to 12 statements. The
2 base statements that differ are the first import (which carries the
module header) and `SchemaSyncHost`. The 5 new statements are the
`@objectstack/types` import, the helper and the three functions.
- **Result.** `PROOF OK`, exit 0.
- **Negative control.** I changed `was NOT created: ` to `was NOT
creat3d: ` in a module copy. The proof then reports 1 token and 1 line
differing, prints `PROOF FAILED`, and exits 1.
## Tests
Each suite ran under its own `os-verify-lock` hold. I compared the
vitest JSON per test name and status, base `e6dfeb08f` against head
`b2b00ab42`:
| 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 |
- **Type check and lint.** `pnpm exec tsc --noEmit` in driver-sql exits
0. `pnpm exec eslint --no-inline-config` on the two touched files exits
0, with 0 problems.
- **Late-binding probe.** This is a scratch script, not committed. It
runs node against each end's built dist on in-memory SQLite. Its 20
readings print identical output at base and head (`diff` is empty). They
cover:
1. `syncDeclaredIndexes` through a `knex` replaced on the instance after
construction;
2. a missing-column skip reaching an instance spy on
`logDurabilityFailure`, and an instance spy on `getExistingIndexNames`;
3. the NULL-safe route reaching a subclass override of
`createNullSafeUniqueIndex`, with the emitted `COALESCE(organization_id,
'__global__')` DDL;
4. a plain unique over seven duplicate groups reaching an instance spy
on the probe, with the durability line `formatDuplicateGroups` renders,
five groups then "…and 2 more";
5. a NULL-safe unique over duplicates logged while the sync goes on to
the next index;
6. `createNullSafeUniqueIndex` through a subclass `isMysql` getter, on
its functional-key-part fallback to the bare composite;
7. `applyNullSafeUniquePreflight` on a dirty create (blocked, with
`applyLimit` and message), a clean tightening (`safe`), and a probe
failure warned through a `logger` replaced after construction;
8. the same pre-flight through an instance spy on the probe;
9. a bad argument to each moved method answering a `TypeError`
rejection, never a synchronous throw.
- **Not run.** No ablation, because no tested behaviour changed.
`test:repo` was not run locally: the diff touches no repo-project test,
and CI's Test Core runs it.
## Gates
All local runs are on head `b2b00ab42`.
- **Derived gates.** `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` derived 55 commands from the change
set against merge base `e6dfeb08f` (2 paths). I captured each exit code
before any pipe.
- 52 exit 0 on the first run.
- `check-plugin-teardown-shape.mjs --self-test` exited 3 on the shallow
clone, then 0 after `git fetch origin 621a487` (its positive control).
- `check:lean-entry-closure` exited 3 with no objectql dist, then 0
after `pnpm turbo run build --filter=@objectstack/objectql` under the
lock.
- `check:dual-build-cjs-loads` exited 3, PREREQUISITE NOT MET: it needs
every package's dist. It is NOT MEASURED locally, and CI runs it.
- **Reconciliation.** `--ran` reports "55 derived famil(ies) accounted
for — 54 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)", exit
0.
- **Card-named gates.** I read each at base in a clean detached worktree
at `e6dfeb08f` and at head `b2b00ab42`. All exit 0 at both ends.
| Gate | Base | Head | Note |
|:--|:--|:--|:--|
| `check:adr-anchors` | 90 anchored files, 1883 citations | same | |
| `check:adr-symbol-anchors` | 2664 anchors resolve | same | |
| `check:tenant-chokepoint` | 24 `getBuilder()` bindings across 3 files;
rule 2 clean | same | See the first acceptance note. |
| `check:logger-receiver-detach` | 0 detaches, 3736 non-test TS files |
0 detaches, 3737 files | The head has one more walked file; the base
worktree lacks the gitignored generated
`packages/spec/src/migrations/registry.ts`. |
| `check:driver-conformance` | 55 covered, 0 DEBT, 0 exempt | same | |
| `check:keyed-text-bounds` | 112 object files, 238 index entries | same
| |
| `check-tenant-audit-census` | 243 write call sites certified | same |
|
- **Not owed.** `check-platform-checklist --changed-from` is not owed:
no exported symbol was renamed or deleted, because
`formatDuplicateGroups` was never exported. Pre-push
`check:commit-card-trailers` and `check:nul-bytes` pass.
- **`origin/main` moved while this ran.** It moved 10 commits, to
`df8aac41f`. None of them touches `packages/drivers/**`,
`scripts/adr-anchors/**`, `check-adr-anchors.mjs` or
`check-tenant-chokepoint.mjs`. Two touch `packages/types/src`, which
driver-sql imports `isUniqueViolationError` from, so CI's merge-ref run
covers that. `git merge-tree` against it is clean. I did not merge,
because CI tests the merge ref.
## Acceptance notes
- **`check:tenant-chokepoint` rule 2 visits a little less.** Rule 2 (the
D8 null-arm rule) scans class members of the three driver files, so it
no longer visits what moved:
- one `knex.raw(` site, `createNullSafeUniqueIndex`'s `CREATE UNIQUE
INDEX` with its `COALESCE(... '__global__')` key part (`sql-driver.ts`
goes from 57 to 56 `.raw(` sites);
- `syncDeclaredIndexes`' `tenantField` parameter and its
`resolveTenantField` binding.
None of these says `IS NULL` against a tenant column, and none is a
`where` arm. The verdict is unchanged, and the gate is not empty (24
bindings, 3 files). This is the same disclosure cuts 5-7 made, and the
card already carries the `SCAN_FILES` precondition.
- **A docblock link no longer resolves in its file.** The docblock of
`reclaimBetterSqlite3` in `sql-driver.ts` says "Module-local, like
{@link formatDuplicateGroups}", and that helper now lives in
`sql-driver-schema-sync.ts`. The sentence is still true, because the
helper is still module-local. I left the docblock unedited, since the
cut is move-only.
- **Proposed next slice: `applyCrossFieldComparison`** (Filter helpers,
about -179, reads 6 methods and no field). It would need a new seam
module. Before pricing it at dispatch, screen it against
`sql-driver-compile-refusal-seam.test.ts` (whether it builds
`INVALID_FILTER`) and against `check:tenant-chokepoint` rule 2.
`skip-changeset`: the change is move-only, so nothing a published
package ships changes. The `.d.ts` is byte-identical, and the emitted JS
runs the same bodies through the host.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01EcqJz48p6ineaiedw6SCaX)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7e4af20 commit ab112ea
2 files changed
Lines changed: 441 additions & 380 deletions
0 commit comments