Repository navigation
Commit 659f2d9
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XWfewWfvar93yD4Po1GfCr7)_
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
## 维护者速读
- **改了什么**:把 `sql-driver.ts` 里「读操作被数据库拒绝时怎么回答」的整组代码(`find`/`count`
的兜底故障信封、WHERE 列找不到时的拒绝、`aggregate` 与 `distinct`
各自的分类器和列拒绝,以及只被它们用到的四个模块级函数)原样搬进新文件
`sql-driver-read-exit-fault.ts`;类上的六个方法全部保留,只把方法体转交过去。
- **为什么改**:#25521 拆分超大文件的第 15 刀;这组是剩余可搬区域里收益最大的一块,`sql-driver.ts` 减少 445
行。
- **风险与回滚**:纯搬移,无行为变化;三个 SQL 驱动的测试两端逐条一致,公开类型声明哈希不变。回滚即还原本 PR。
- **先看**:`sql-driver-read-exit-fault.ts` 的头注释与
`ReadExitFaultHost`;`sql-driver.ts`
中六个方法的转交桩;`sql-driver-compile-refusal-seam.test.ts` 新增的那一个扫描文件。
- **两分钟验证**:`pnpm --filter @objectstack/driver-sql exec vitest run
src/sql-driver-backend-fault-envelope.test.ts
src/sql-driver-compile-refusal-seam.test.ts
src/sql-driver-unresolvable-where-column-refusal.test.ts`,预期全部通过。
- **需要你做的**:无,席位落地。
## What changes
Cut 15 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6432488188`. The cut opens with a fresh
seam table (below), taken on `origin/main` `d1a2e71a3` (cut 14's merge),
and takes the area that pays best without breaking a series limit: the
**fault terminals of the read exits**, what a read answers when the
backend refused its statement. It moves unedited into a **new** seam
module, `packages/drivers/driver-sql/src/sql-driver-read-exit-fault.ts`,
through a new host `ReadExitFaultHost`:
- `backendStatementFault`, the #8931 terminal that `find` and `count`
end in;
- `unresolvableFilterColumnRefusal`, #8790's `INVALID_FILTER` for a
WHERE column the database could not resolve;
- `aggregateBackendFault` (#11455 / #11541) and `distinctBackendFault`
(#17639 / #17857), the classifiers of `aggregate` and `distinct`, each
of which ends in one of the two above or in its own column refusal;
- `unresolvableAggregateColumnRefusal` and
`unresolvableDistinctColumnRefusal`, those two column refusals.
With them go the four module-level declarations only they read: the
#8931 envelope `backendStatementFaultError`, #8790's
`unresolvableFilterColumnError`, the dialect-message reader
`unresolvableColumnNameOf` and the #20020 attribution walk
`unresolvableColumnProvenance`. The `[#21385]` import of
`redactStatementFromMessage` follows its last reader into the module,
with its own comment.
The change is move-only, and the card stays open for later cuts. There
is no `docs/adr/**` edit, no `packages/spec/**` edit, no anchor entry
change, no gate edit and no new gate. Two tests change, and only as path
readers (below). Branch `claude/project-thread-uliqpv` (the platform
assigned it to this card thread, as the claim records). The move is one
commit, `ef0640e10`, on `d1a2e71a3`.
**Net line count (the seat's rule).** `sql-driver.ts` goes from 19,794
lines to 19,349: **-445**.
- **Out:** the six bodies, 189 lines (15 + 87 + 23 + 25 + 16 + 23). The
four declarations, 293 lines with their own docblocks (144 + 54 + 41 +
54), plus 4 separator lines. The `redactStatementFromMessage` import and
its 6-line comment, 7 lines. Two names (`declareTargetedTable`,
`isMissingTableError`) from the `@objectstack/types` import, 2 lines.
- **In:** the six stub bodies, 46 lines (8 + 12 + 7 + 6 + 7 + 6), and a
4-line import of the module with its comment.
- The new module is 607 lines.
**Path readers migrated in the same commit (both tests, no assertion
changed).**
- `sql-driver-compile-refusal-seam.test.ts` enumerates every
`INVALID_FILTER` builder by parsing a fixed list of source files, and
asserts `unresolvableFilterColumnError` is one of the three direct
callers. That function now lives in the new module, so the list gains it
(one line, plus its comment and the two docblocks that name the list).
The direct-caller set it asserts is unchanged.
- `sql-driver-unresolvable-where-column-refusal.test.ts` imports
`unresolvableColumnNameOf` from the new module instead of
`./sql-driver.js`.
**Serial with the file's in-flight PRs.** I read the file list of every
open PR (23, by fetching each head and diffing it against its merge base
with `origin/main`) before the first edit. None touches `sql-driver.ts`,
`turso-driver.ts`, `sqlite-wasm-driver.ts`,
`check-tenant-chokepoint.mjs` or the driver-sql anchor entries. #26138
touches `driver-sql/src/builtin-column-collision.ts` only; #26337 adds
`driver-sql/src/sql-driver-external-unprovisioned-sort-anchor.test.ts`
only, which reads none of the moved members. Re-measured before
`pr_create` (21 open PRs): #26451 edits the five drivers' `package.json`
only, and #26337 is as above; neither touches this region.
## Seam table, fresh, on `d1a2e71a3`
- **Size and churn.** `sql-driver.ts` is 19,794 lines. The 30-day column
counts `git blame` lines from commits on or after 2026-09-27T03:11:08Z,
30 days before the base commit. History reaches 2026-09-18.
`scripts/pm/git-history.mjs count` proves 75 commits on the file in 30
days and 33 in the last 7. In all, 3,481 lines (17.6%) are from the last
30 days.
- **Class shape.** `SqlDriver` spans lines 5149-19719 with 350 members:
243 instance methods, 13 accessors and 32 statics, all 32 private or
protected.
- **How it was measured.** The same TypeScript compiler AST script cuts
9-14 used, which strips casts, parentheses, `!` and `satisfies` before
it reads `this`. Sections are the class's own banner comments.
| Lines | Section | First … last member | Lines | 30-day | Methods
(public) | Inferred public | getBuilder sites | Statics
(private/protected) |
|:--|:--|:--|--:|--:|:--|--:|--:|:--|
| 1-5148 | Module preamble | - | 5,148 | 793 | - | - | - | - |
| 5149-6740 | Class head: fields, statics, constructor, capability
getters | `name` … `assertDialectEmits` | 1,592 | 290 | 8 (1) | 1 | 0 |
18 (18) |
| 6741-7172 | Lifecycle | `connect` … `disconnect` | 432 | 155 | 8 (3) |
0 | 0 | 6 (6) |
| 7173-9579 | CRUD — IDataDriver core | `find` … `delete` | 2,407 | 745
| 43 (7) | 0 | 12 | 0 (0) |
| 9580-10191 | Bulk & Batch Operations | `bulkCreate` … `count` | 612 |
119 | 9 (6) | 0 | 7 | 0 (0) |
| 10192-10288 | Raw Execution | `rawStatementFault` …
`noteRuntimeIndexDdl` | 97 | 28 | 3 (1) | 0 | 0 | 0 (0) |
| 10289-10381 | Transactions | `beginTransaction` …
`rollbackTransaction` | 93 | 46 | 7 (5) | 0 | 0 | 0 (0) |
| 10382-10913 | Aggregation | `aggregate` …
`unresolvableAggregateColumnRefusal` | 532 | 60 | 5 (1) | 0 | 1 | 0 (0)
|
| 10914-11201 | Distinct | `distinct` …
`unresolvableDistinctColumnRefusal` | 288 | 17 | 3 (1) | 0 | 1 | 0 (0) |
| 11202-11317 | Window Functions | `findWithWindowFunctions` …
`findWithWindowFunctions` | 116 | 4 | 1 (1) | 0 | 1 | 0 (0) |
| 11318-11416 | Query Plan Analysis | `explain` … `analyzeQuery` | 99 |
1 | 2 (2) | 0 | 1 | 0 (0) |
| 11417-11475 | Schema Sync (syncSchema / init) | `syncSchema` …
`reclaimSpace` | 59 | 34 | 3 (3) | 0 | 0 | 0 (0) |
| 11476-13024 | Schema Sync (syncSchema / init) › Data-lifecycle
rotation (ADR-0057 P2) | `rotationStateByTable` …
`migrateMysqlTimeColumns` | 1,549 | 158 | 26 (4) | 0 | 0 | 0 (0) |
| 13025-13281 | Schema Sync (syncSchema / init) › Deferred schema DDL
(#3917) | `setDeferredDdl` … `flushDeferredSchemaDdl` | 257 | 25 | 6 (4)
| 0 | 0 | 0 (0) |
| 13282-14096 | Schema Sync (syncSchema / init) › Managed-schema drift &
reconcile (#2186) | `dialectName` … `createNullSafeUniqueIndex` | 815 |
237 | 23 (3) | 0 | 0 | 0 (0) |
| 14097-14148 | Schema Introspection | `listPhysicalColumns` …
`introspectSchema` | 52 | 46 | 2 (2) | 0 | 0 | 0 (0) |
| 14149-14419 | Internal helpers | `getKnex` … `auditMissingTenant` |
271 | 73 | 8 (1) | 0 | 1 | 0 (0) |
| 14420-16569 | Internal helpers › Filter helpers |
`tableNameForBuilder` … `applyFalseConstant` | 2,150 | 354 | 44 (2) | 0
| 0 | 0 (0) |
| 16570-16745 | Internal helpers › Field mapping | `mapSortField` …
`mapAggregateFunc` | 176 | 2 | 6 (0) | 0 | 0 | 0 (0) |
| 16746-16793 | Internal helpers › Window function builder |
`buildWindowFunction` … `buildWindowFunction` | 48 | 26 | 1 (0) | 0 | 0
| 0 (0) |
| 16794-18740 | Internal helpers › Column creation helper |
`nowColumnDefault` … `applyDeclaredColumnDefault` | 1,947 | 92 | 19 (0)
| 0 | 0 | 8 (8) |
| 18741-19038 | Internal helpers › Database helpers | `sqliteFilename` …
`isJsonField` | 298 | 76 | 9 (2) | 0 | 0 | 0 (0) |
| 19039-19515 | Internal helpers › SQLite serialisation | `formatInput`
… `formatOutput` | 477 | 27 | 2 (0) | 0 | 0 | 0 (0) |
| 19516-19719 | Internal helpers › Introspection internals |
`introspectColumnOrder` … `introspectUniqueConstraints` | 204 | 73 | 5
(0) | 0 | 0 | 0 (0) |
| 19720-19794 | After the class | - | 75 | 0 | - | - | - | - |
### Pricing the areas
Eligibility is as cuts 11-14 defined it: an annotated return type or not
public; no `getBuilder`, `this.FIELD.delete/insert/update(`,
private-static, `super`, bare-`this` or `this`-write site; not
`insertOnlyUpsertColumns`. 141 members are eligible on this base. Each
area is priced as its stubs minus its bodies, then net of the
module-level declarations it shares with members that stay (they stay in
place, exported; ⛔ no second copy of a helper), counting only a
declaration's own docblock (cut 14's correction: the move script refuses
a declaration whose leading trivia is not exactly one JSDoc block
directly above it, and none of the four had another comment).
| Area | Bodies | Bodies net | Declarations that move along |
Disposition |
|:--|--:|--:|--:|:--|
| **Read-exit fault terminals** (`backendStatementFault`,
`unresolvableFilterColumnRefusal`, `aggregateBackendFault`,
`distinctBackendFault`, `unresolvableAggregateColumnRefusal`,
`unresolvableDistinctColumnRefusal`) | 6 | **-143** | **-297** (the four
above with docblocks and separators), -5 net for imports | **Moves (this
cut).** -445 measured. |
| `backendStatementFault` alone (cut 14's priced next slice) | 1 | -75 |
-145 (`backendStatementFaultError`), +4 for the import | Subsumed: about
-216, the first row's largest part. Taken alone it leaves its three
callers' siblings behind, and
`aggregateBackendFault`/`distinctBackendFault` call it. |
| Rotation sub-banner (`ensureRotation`, `registerExternalObject`,
`warnBuiltinColumnCollisions`) | 3 | about -118 | 0 | Not taken:
`migrateMysqlDatetimeColumns`/`migrateMysqlTimeColumns` stay (cut 12
durability trap), `ensureShardTable` is named by
`check-object-def-param-keys.mjs` and `computeTenantField` by
`packages/spec/liveness/object.json`. |
| The rest of the Filter helpers (`compileFilters` -75,
`applyNormalizedComparison` -60, …) | - | - | - | Not priced as one
area: small bodies spread around `applyFilterCondition`, which an
ADR-0139 pointer pins in place. |
## Why
### Why this area, as one area
- **One mechanism.** Every read exit catches its statement's failure and
hands it to this family: `findRows` and `count` to
`unresolvableFilterColumnRefusal` or the `backendStatementFault`
terminal; `aggregate` to `aggregateBackendFault`, which ends in its
column refusal, the WHERE refusal or the terminal; `distinct` to
`distinctBackendFault`, the same shape. The six bodies only classify an
error the exit already caught and compose the envelope; none runs a
statement. They sit under three banners (Bulk, Aggregation, Distinct)
only because each sits next to the exit that calls it.
- **It pays the most of any area that moves cleanly**, about twice the
lone terminal.
- **What stays, and why.**
- The exits themselves (`findRows`, `count`, `aggregate`, `distinct`)
build through `getBuilder`, and stay.
- `isUnresolvableColumnError` (also read by `findRows` and `count`),
`OWN_STATEMENT_FAULT` (read by `sql-driver-raw-execution.ts`, which
imports it from `sql-driver.ts`), `PRE_DDL_QUESTION_SCOPE` (also run by
the two media-arm resolvers), `unsupportedFilterError` and
`isFilterNode` (each read by much of the filter compiler) are shared.
The three that were not exported gain a leading `export` and nothing
else, and the module imports all five back. The module reads them only
inside function bodies, so the import cycle is evaluation-safe.
`index.ts` names its exports one by one; the export lists below prove
none of them leaks.
- `mapSortField` and `remoteColumn` are read by members that stay too;
the moved bodies reach them through the host.
- **No series limit is touched.** None of the six builds through
`getBuilder`, reads a static, has a `this.FIELD.delete/insert/update(`
site, uses `super` or a bare `this`, or writes to `this`. Every one has
an annotated return type and is protected. `check:tenant-chokepoint`'s
D8 predicates, measured with its own `nullArmsOf`: **4 at base and 4 at
head**, all in `sql-driver.ts`, 0 in the moved bodies (none reads a
tenant field).
- **Durability gate.** The moved code has no `catch` clause (the word
appears only in comments: one docblock heading and two `catch-all`
notes). `check:durability-log-level --list` gives the same seams at both
ends, line numbers aside; the gate reads 48 seams (7 propagating) and 82
read seams at both ends.
- **Logger.** Four bodies write `this.logger.warn(` /
`this.logger.debug?.(`; the host carries `logger` as a getter, so the
receiver is the driver's logger as before.
`check:logger-receiver-detach`: 0 detaches at both ends.
- **Subclasses.** `TursoDriver` calls `aggregateBackendFault` and
`distinctBackendFault` on its own instance;
`sql-driver-21385-refusal-log-line-redaction.test.ts` overrides four of
the six in a subclass and calls `super`. Every stub keeps its signature
and stays `protected`, and every member a body calls is a late-bound
closure on the instance (probe below).
- **Path readers, screened.** No script, test, doc or ADR names any of
the six, or the four moved declarations, by a `sql-driver.ts#…` pointer
or a `sql-driver.ts::…` key, and no `scripts/adr-anchors/**` record
names them. Tests that read `sql-driver.ts` as text: the five cli
generate pins (they read `createColumn`, which stays),
`logger-receiver-detach.test.ts` (it scans for detach shapes, finds none
either way), and the compile-refusal seam test (migrated above). Prose
mentions elsewhere (`turso-driver.ts`, `engine.ts`, the runtime noise
filters, the types predicates' tests, CHANGELOGs) name the functions,
and each is still true.
## The shape (#23050 shape B, as cuts 1-14 apply it)
- Each class method keeps its docblock and signature, byte-identical.
Its body is now one host literal plus `NAME.call(host, ...)`, marked
`[#25521 cut 15]`.
- Fields go as GETTERS that read the driver at call time (`logger`,
`physicalTableByObject`, `deferredDdl`, `deferredSchemaObjects`).
Methods go as closures that call the method on the driver at call time
(`mapSortField`, `remoteColumn`, `backendStatementFault`, and the three
refusals). So a subclass override, an instance spy, or a field replaced
after construction is still the one the body reaches.
- `ReadExitFaultHost` lists exactly those ten members, each typed as the
class member's indexed access. There is no cast, and no member becomes
public.
- **Module imports.** `StandardErrorCode` (`@objectstack/spec/api`),
`type DriverQuery` (`@objectstack/spec/contracts`),
`resolveFilterSubtreeProvenance` (`@objectstack/spec/data`, still read
in `sql-driver.ts` too), `declareTargetedTable` and
`isMissingTableError` (`@objectstack/types`, whose last readers in
`sql-driver.ts` moved, so they leave its import), the moved
`redactStatementFromMessage` import, and from `./sql-driver.js` the five
shared declarations plus `type SqlDriver`.
- **Comments.** The module header says what moved, what stayed and why.
The `sql-driver.ts` import comment names cut 15 in 3 lines. The header
cites no `ADR-NNNN Dn`.
- **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 body
line starts inside a template literal.
## Verification
### ADR anchors
- **The count.** `check:adr-anchors` counts **1876** decision-letter
citations at base `d1a2e71a3` (a clean detached worktree) and **1876**
at head, over 91 anchored files at both ends. Both runs exit 0.
- **Why equal.** No comment inside the moved bodies, declarations or
import cites a decision letter. The stubs keep their docblocks, so every
`ADR-…` mention in them stays in `sql-driver.ts`.
- **No entry needs a new home.** The `sql-driver.ts` entry's one
paragraph (ADR-0053) describes `formatOutput` and `presentReadValue`,
neither of which moved. `check:adr-symbol-anchors`: 2664 resolve at both
ends.
### The published `.d.ts` does not change
This is measured under the series bar (ruling `6348891160`, item 1).
- **How each end was built.** `pnpm turbo run build
--filter=@objectstack/driver-sql --force` at each end, against the same
dependency tree. The base leg writes base `sql-driver.ts` and the two
base test files into this worktree and deletes the new module, under an
EXIT/INT/TERM trap that restores HEAD. The restore is proved by the HEAD
blob hashes (`4aeac25e`, `dc34f18e`, and both tests), 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,
`0f33bf3febaac3c7aa96f68a4226d752766b8203ab7acade523b69f9aaa44d74`
(unchanged since cut 8).
- **Positive control.** I dropped `protected` from
`backendStatementFault` in the head `index.d.ts`. The result hashes to
`2e64636ebed0f4461e048dc1d3fa09a07c4172c537607d7024a2b36038eee409`, with
a 1-line diff and `cmp` exit 1.
- **Export lists.** CJS `require` of the head dist gives 59 names (sha1
`05757ce5ae`); the ESM export statement of the base and head `index.mjs`
lists the same 59 names (sha1 `05757ce5ae` both). None of the three
newly exported declarations, and nothing from the new module, is among
them.
- **The head dist carries the move.** `.call(host` sites in `index.mjs`
go from 51 at base to 57 at head (six stubs).
### Move-only proof
The proof compares TypeScript compiler AST leaf tokens (JSDoc nodes
skipped), base `d1a2e71a3` against head `ef0640e10`. It is a scratch
script and is not committed.
| Moved body | Body tokens | Comments | Parameter tokens less `this` |
Return type tokens | Body lines |
|:--|--:|--:|--:|--:|--:|
| `unresolvableFilterColumnRefusal` | 136 | 0 | 10 | 1 | 15 |
| `backendStatementFault` | 245 | 44 | 6 | 1 | 87 |
| `aggregateBackendFault` | 156 | 7 | 9 | 1 | 23 |
| `unresolvableAggregateColumnRefusal` | 161 | 0 | 20 | 1 | 25 |
| `distinctBackendFault` | 69 | 6 | 13 | 1 | 16 |
| `unresolvableDistinctColumnRefusal` | 134 | 4 | 9 | 1 | 23 |
- **Each moved body.** In every row, 0 tokens differ and every comment
is identical. Each body line is the base line less two leading spaces.
None is `async`, at either end.
- **The six stubs.** Leading trivia (the docblock), modifiers and the
signature are identical to base.
- **The class.** It has 350 members at both ends, in the same order, and
the 344 unmoved members are byte-identical, trivia included.
- **Module-level declarations.** The four that moved are byte-identical
in the module from their own docblock on, and gone from `sql-driver.ts`.
The three newly exported ones differ from base by a leading `export` and
nothing else. The `redactStatementFromMessage` import moved whole with
its comment (7 lines). At `sql-driver.ts`'s top level, 189 of 199 base
statements are byte-identical; the rest are the four moved declarations,
the three exports, the moved import, the `@objectstack/types` import
(less two names) and the class. The one head-only statement besides
those is the new import.
- **Result.** `PROOF OK`, exit 0.
- **Negative control.** Through `scripts/ablation-replace.mjs`, I
changed `typeof declared === 'number'` to `'string'` in the module's
`backendStatementFault` (1 hit, checked on disk). The proof then reports
`backendStatementFault` with its body tokens differing, prints `PROOF
FAILED`, and exits 1. The restore was proved (blob equals HEAD, empty
`git diff HEAD`).
### Tests
Each end ran under one `os-verify-lock` hold, after building that end's
driver-sql dist. I compared the vitest JSON per test name and status,
base `d1a2e71a3` against head `ef0640e10`. Every part's exit code was
captured on its own (build, probe, three suites: all 0 at both ends).
| Suite | Base | Head | Lost / changed / added |
|:--|:--|:--|:--|
| `@objectstack/driver-sql` | 4060 (3846 passed, 214 skipped; 248 files)
| same | 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` | 746 (746 passed; 39 files) | same
| 0 / 0 / 0 |
- **Type check and lint.** `tsc --noEmit -p .` in driver-sql exits 0.
`pnpm exec eslint --no-inline-config packages/drivers/driver-sql` exits
0.
- **Late-binding probe.** A scratch script, not committed. It runs node
against each end's built dist on in-memory SQLite and prints 48
readings, each with the envelope's message, `code`, `status`, `cause`,
own keys and symbol-keyed members (the declared target table), the log
lines written, and the instance spies hit in order:
1. `backendStatementFault` on a declared error (returned as the same
object), five undeclared ones, a federated object (the declared target
follows `physicalTableByObject`), and the three deferred-DDL cases
(demoted to `debug`, warned, warned);
2. `unresolvableFilterColumnRefusal` with no filter, an author-marked,
an unmarked and a policy-marked filter, and an unnamed column;
3. `aggregateBackendFault` on a groupBy column (string and structured),
an aggregation column, both, a WHERE column, an unnamed column and
another fault;
4. `distinctBackendFault` on the listed field, a filter column, an
unnamed column and another fault;
5. the two column refusals directly, on every `namedBy` shape;
6. a SUBCLASS overriding the four refusal/terminal methods,
`mapSortField` and `remoteColumn`, each reached through the classifiers;
`logger`, `physicalTableByObject`, `deferredDdl` and
`deferredSchemaObjects` replaced on the instance after construction (the
new ones are the ones read);
7. eight `find`/`count`/`aggregate`/`distinct` calls end to end on
SQLite, on a missing table and on a dropped column;
8. bad arguments on three of the methods.
- **Probe result.** 33 of the 48 readings are identical, envelopes and
log lines included. The other 15 differ only in the top stack frame's
receiver name, where the error is constructed inside a moved body:
`_SqlDriver.X` (or `Sub.X`) at base and `Object.X` at head. With that
receiver name normalised, the two outputs are byte-identical. That is
the host-literal receiver of shape B, the same at every earlier cut, and
no test or consumer reads it.
- **Not run.** No ablation, because no tested behaviour changed.
- **`test:repo`.** After the merge of `origin/main` (`3b5318a22a`), each
under the lock after building its closure: the `repo` projects of types
(11 passed), core (83), objectql (5), spec (1293), rest (280 passed, 18
skipped) and runtime (947) all pass, exit 0.
### Gates
- **Merge of `origin/main`.** `3b5318a22a` merges 9 commits that touch
no `packages/drivers/**` file and no gate this cut reads. After it, `tsc
--noEmit -p .` in driver-sql exits 0 and `check:adr-anchors` still reads
1876.
- **Derived list.** `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` derives 54 commands for the changed
paths, the same 54 before and after the merge. On `3b5318a22a`, 53 exit
0. `check:dual-build-cjs-loads` exits 3, `PREREQUISITE NOT MET` (no full
build here): **NOT MEASURED** locally, CI runs it. The teardown
self-test's pinned commit was fetched first, and objectql was built for
`check:lean-entry-closure`.
- **Reconciliation.** `dispatch-gates --ran`: 54 derived families
accounted for, 53 run, 1 NOT-MEASURED (derived from the recorded exit
3), exit 0.
- **Card-named gates, read at base (a clean detached worktree at
`d1a2e71a3`) and at head (`ef0640e10`; the derived ones again on the
merged head `3b5318a22a`), all exit 0:**
| Gate | Base | Head |
|:--|:--|:--|
| `check:adr-anchors` | 91 files, 1876 decision-letter citations | 91
files, 1876 |
| `check:adr-symbol-anchors` | 2664 resolve | 2664 resolve |
| `check:tenant-chokepoint` | 24 bindings / 3 files, D8 clean; 4 tenant
predicates | same; 4 tenant predicates |
| `check:durability-log-level` | 48 seams, all loud (7 propagating); 82
read seams | same; `--list` equal but for line numbers |
| `check:driver-conformance` | 55 covered / 0 DEBT | same |
| `check:keyed-text-bounds` | 112 files / 238 index entries | same |
| `check:object-def-param-keys` | 3329 files / 545 classes / 7 positions
| 3331 files on the merged head (the new module, plus what `main`
brought) / 545 / 7 |
| `check:system-context-census` | 153 sites / 132 symbols | same |
| `check-tenant-audit-census` | 244 sites | same |
| `check:logger-receiver-detach` | 0 detaches | 0 detaches (one more
file walked) |
- `check:nul-bytes` passes. `check-platform-checklist --changed-from
origin/main` (a moved exported function) passes: 6 anchors judged, 0
lost. The pre-push hooks passed on push.
## Acceptance notes
- **`OWN_STATEMENT_FAULT` has no reader left in `sql-driver.ts`.** Its
readers in the file were the three column refusals and the terminal, all
moved; `sql-driver-raw-execution.ts` and the new module import it from
there. It stays where it is: moving it would edit the raw-execution
module's import for no line it pays, and one home is kept either way.
The raw-execution header's phrase "`OWN_STATEMENT_FAULT` has readers
that did not move" now means readers outside that module. Noted, not
filed.
- **`check:tenant-chokepoint`'s `SCAN_FILES` does not list the new
module.** The moved bodies hold 0 of the file's 4 tenant predicates and
build no query. Noted, not filed: widening `SCAN_FILES` would be a gate
change.
- **Next slice, priced on this base.** The rotation sub-banner is now
the largest clean area (`ensureRotation`, `registerExternalObject`,
`warnBuiltinColumnCollisions`, about -118, with the durability-trap and
path-reader members staying). The series' remaining yield outside the
pinned methods (`createColumn`, `applyFilterCondition`,
`formatInput`/`formatOutput`, `initObjects`) is small bodies of under
-70 each.
## Human Minimum
- [x] 1. No `packages/spec` change.
- [x] 2. The one new name, `ReadExitFaultHost`, follows the interface
casing.
- [x] 3. No formatter ran; scoped `eslint --no-inline-config` passes
(repo-wide `pnpm lint` is CI's run).
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. No publishable behaviour change: `skip-changeset`; both
declaration lines above.
- [x] 6. `packages/spec` not touched.
- [x] 7. No hand edits to generated docs, changelogs or release notes.
- [x] 8. Title, body and comments are in English (the maintainer brief
excepted).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FEkQ5mL6cyUGiP87zTtR7y)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5mL6cyUGiP87zTtR7y
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 00874b9 commit 659f2d9
4 files changed
Lines changed: 670 additions & 502 deletions
File tree
- packages/drivers/driver-sql/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
272 | 273 | | |
273 | 274 | | |
274 | 275 | | |
275 | | - | |
276 | | - | |
| 276 | + | |
| 277 | + | |
277 | 278 | | |
278 | 279 | | |
279 | 280 | | |
| |||
284 | 285 | | |
285 | 286 | | |
286 | 287 | | |
| 288 | + | |
| 289 | + | |
287 | 290 | | |
288 | 291 | | |
289 | 292 | | |
| 293 | + | |
290 | 294 | | |
291 | 295 | | |
292 | 296 | | |
| |||
0 commit comments