Repository navigation
Commit 80064b2
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XGbGfWGnrELnWaCK4iybm1t)_
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
## 维护者速读
- **改了什么**:把 `sql-driver.ts` 里「按日/周/月/季/年分组时,各数据库方言生成什么 SQL
分桶表达式」这一个机制(`buildDateBucketExpr` 的方法体)原样搬进新建的
`sql-driver-date-bucket.ts`;类上的方法、文档注释和签名全部保留,只把方法体转交过去,宿主接口
`DateBucketHost` 恰好列出方法体读的 6 个成员。
- **为什么改**:#25521 拆分超大文件的第 20 刀;第 19
刀合入后重新测量,这是仍成「一个机制」、收益最大且不碰任何系列限制的区域,`sql-driver.ts` 减少 39 行。
- **风险与回滚**:纯搬移,无行为变化;三个 SQL 驱动的测试两端逐条一致,公开类型声明哈希不变,344 条探针读数两端一致(仅 1
条栈顶接收者名不同)。回滚即还原本 PR。
-
**先看**:`sql-driver-date-bucket.ts`(头注释、`DateBucketHost`、函数体);`sql-driver.ts`
中 `buildDateBucketExpr` 的转交桩;`sql-driver.ts` 新增的 3 行 import。
- **两分钟验证**:`pnpm --filter @objectstack/driver-sql exec vitest run
src/sql-driver-date-bucket.test.ts
src/sql-driver-21485-date-bucket-calendar-day.test.ts
src/sql-driver-temporal-dialect.test.ts`,预期全部通过。
- **需要你做的**:无,席位落地。
## What changes
Cut 20 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6456805734`. Cut 19 (#26960) merged first,
as `d7f76b6d97`; this cut opens with a fresh seam table taken on
`origin/main` `6845035c6b` (below) and takes the largest area that is
one mechanism and moves cleanly: **date bucketing**,
`buildDateBucketExpr`, from the class head. Its body moves unedited into
a **new** seam module,
`packages/drivers/driver-sql/src/sql-driver-date-bucket.ts`, through its
host `DateBucketHost`.
`buildDateBucketExpr` is the per-dialect SQL fragment a date dimension
groups by at `day`, `week`, `month`, `quarter` or `year`: PostgreSQL
`to_char`, MySQL `date_format`, SQLite `strftime`, with the #21485
calendar-day arm for a `Field.date` and the #21595 Thursday-rule ISO
week on SQLite. It returns `null` for a granularity the dialect does not
model. Its two callers stay in the class: `aggregate` (the GROUP BY) and
`dateBucketSql` (the printed form `service-analytics` echoes).
**Why a new module.** No existing seam module holds anything about
aggregation or temporal read expressions; the nearest
(`sql-driver-schema-sync.ts`) is DDL. The new module imports
`sql-driver.ts` for a type only (`import type { SqlDriver }`), so it
adds no evaluation cycle, and the body reads no module-level
declaration, so nothing gains `export` and nothing else moves.
**`DateBucketHost`** lists exactly the six members the body reads, each
typed as the class member (`SqlDriver['NAME']`): the `isPostgres`,
`isMysql` and `isSqlite` flags and the protected
`dateGranularityCapabilities` getter (as getters), and the protected
`temporalFieldKind` and `sqliteTemporalArg` methods (as late-bound
closures). All six are read by members that stay as well.
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, no test edit and no new gate. Branch
`claude/project-thread-p875md` (the platform assigned it to this card
thread, as the claim records). The move is one commit, `7c6f6f1fe`, on
`6845035c6b`.
**Net line count (the seat's rule).** `sql-driver.ts` goes from 18,406
lines to 18,367: **-39**.
- **Out:** the body, 56 lines.
- **In:** the stub body, 14 lines, and 3 import lines (a 2-line comment
and the `./sql-driver-date-bucket.js` import, placed after cut 16's seam
import).
- `sql-driver-date-bucket.ts` is new: 119 lines (a 40-line header, the
type import, the 15-line host and the function with its one-line
docblock).
**Path readers.** No test, script, doc, ADR or anchor entry reads the
body by path, so none is migrated (screen below).
**Serial with the file's in-flight PRs.** I read the file list of every
open PR on `objectstack-ai/objectstack` at the start (41) and again
before opening this one (26). None touches
`packages/drivers/driver-sql/**`.
## Seam table, fresh, on `6845035c6b`
- **Size and churn.** `sql-driver.ts` is 18,406 lines. The 30-day column
counts `git blame` lines from commits on or after 2026-09-28T06:00Z.
`scripts/pm/git-history.mjs count --ref=origin/main` counts 77
first-parent commits on the file in 30 days and 31 in the last 7 (the
split cuts are most of them). In all, 3,326 lines (18.1%) are from the
last 30 days.
- **Class shape.** `SqlDriver` spans lines 4247-18331 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-19 used, which strips casts, parentheses, `!` and `satisfies` before
it reads `this`. Sections are the class's own banner comments. The file
is byte-identical to #26960's head, so only the 30-day column moved from
the pre-measure I took while #26960 was in the queue.
| Lines | Section | First … last member | Lines | 30-day | Methods
(public) | Inferred public | getBuilder sites | Statics
(private/protected) |
|:--|:--|:--|--:|--:|:--|--:|--:|:--|
| 1-4246 | Module preamble | - | 4,246 | 698 | - | - | - | - |
| 4247-5838 | Class head: fields, statics, constructor, capability
getters | `name` … `assertDialectEmits` | 1,592 | 216 | 8 (1) | 1 | 0 |
18 (18) |
| 5839-6270 | Lifecycle | `connect` … `disconnect` | 432 | 155 | 8 (3) |
0 | 0 | 6 (6) |
| 6271-8677 | CRUD — IDataDriver core | `find` … `delete` | 2,407 | 745
| 43 (7) | 0 | 12 | 0 (0) |
| 8678-9207 | Bulk & Batch Operations | `bulkCreate` … `count` | 530 |
70 | 9 (6) | 0 | 7 | 0 (0) |
| 9208-9304 | Raw Execution | `rawStatementFault` …
`noteRuntimeIndexDdl` | 97 | 28 | 3 (1) | 0 | 0 | 0 (0) |
| 9305-9397 | Transactions | `beginTransaction` … `rollbackTransaction`
| 93 | 46 | 7 (5) | 0 | 0 | 0 (0) |
| 9398-9894 | Aggregation | `aggregate` …
`unresolvableAggregateColumnRefusal` | 497 | 54 | 5 (1) | 0 | 1 | 0 (0)
|
| 9895-10156 | Distinct | `distinct` …
`unresolvableDistinctColumnRefusal` | 262 | 26 | 3 (1) | 0 | 1 | 0 (0) |
| 10157-10272 | Window Functions | `findWithWindowFunctions` …
`findWithWindowFunctions` | 116 | 4 | 1 (1) | 0 | 1 | 0 (0) |
| 10273-10371 | Query Plan Analysis | `explain` … `analyzeQuery` | 99 |
1 | 2 (2) | 0 | 1 | 0 (0) |
| 10372-10430 | Schema Sync (syncSchema / init) | `syncSchema` …
`reclaimSpace` | 59 | 34 | 3 (3) | 0 | 0 | 0 (0) |
| 10431-11855 | Schema Sync (syncSchema / init) › Data-lifecycle
rotation (ADR-0057 P2) | `rotationStateByTable` …
`migrateMysqlTimeColumns` | 1,425 | 219 | 26 (4) | 0 | 0 | 0 (0) |
| 11856-12036 | Schema Sync (syncSchema / init) › Deferred schema DDL
(#3917) | `setDeferredDdl` … `flushDeferredSchemaDdl` | 181 | 46 | 6 (4)
| 0 | 0 | 0 (0) |
| 12037-12851 | Schema Sync (syncSchema / init) › Managed-schema drift &
reconcile (#2186) | `dialectName` … `createNullSafeUniqueIndex` | 815 |
237 | 23 (3) | 0 | 0 | 0 (0) |
| 12852-12903 | Schema Introspection | `listPhysicalColumns` …
`introspectSchema` | 52 | 46 | 2 (2) | 0 | 0 | 0 (0) |
| 12904-13174 | Internal helpers | `getKnex` … `auditMissingTenant` |
271 | 73 | 8 (1) | 0 | 1 | 0 (0) |
| 13175-15224 | Internal helpers › Filter helpers |
`tableNameForBuilder` … `applyFalseConstant` | 2,050 | 323 | 44 (2) | 0
| 0 | 0 (0) |
| 15225-15400 | Internal helpers › Field mapping | `mapSortField` …
`mapAggregateFunc` | 176 | 2 | 6 (0) | 0 | 0 | 0 (0) |
| 15401-15448 | Internal helpers › Window function builder |
`buildWindowFunction` … `buildWindowFunction` | 48 | 26 | 1 (0) | 0 | 0
| 0 (0) |
| 15449-17352 | Internal helpers › Column creation helper |
`nowColumnDefault` … `applyDeclaredColumnDefault` | 1,904 | 101 | 19 (0)
| 0 | 0 | 8 (8) |
| 17353-17650 | Internal helpers › Database helpers | `sqliteFilename` …
`isJsonField` | 298 | 76 | 9 (2) | 0 | 0 | 0 (0) |
| 17651-18127 | Internal helpers › SQLite serialisation | `formatInput`
… `formatOutput` | 477 | 27 | 2 (0) | 0 | 0 | 0 (0) |
| 18128-18331 | Internal helpers › Introspection internals |
`introspectColumnOrder` … `introspectUniqueConstraints` | 204 | 73 | 5
(0) | 0 | 0 | 0 (0) |
| 18332-18406 | After the class | - | 75 | 0 | - | - | - | - |
### Pricing the areas
Eligibility is as cuts 11-19 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`; not a member pinned in place (`createColumn`,
`applyFilterCondition`, `formatInput`/`formatOutput`, `initObjects`,
`ensureShardTable`, `computeTenantField`,
`migrateMysqlDatetimeColumns`/`migrateMysqlTimeColumns`,
`compileFilters`). Each area is priced per mechanism (cut 19's
correction), as its stubs minus its bodies, then net of its import
edits. The two leading rows were measured by running the move script on
a scratch copy of the file; the rest are the stub estimate (a stub costs
4 lines, +2 per field read, +1 per method read).
| Area | Bodies | Bodies net | Declarations and imports | Disposition |
|:--|--:|--:|--:|:--|
| **Date bucketing** (`buildDateBucketExpr`) | 1 | -42 (measured) | 0
declarations; +3 for the new module's import and its 2-line comment |
**Moves (this cut).** -39 measured. |
| Presumed-timestamp update (`updateWithPresumedTimestamp` -31,
`resolveUpdatedAtColumnPresence` -6) | 2 | -37 (measured) | No existing
module fits; a new module costs +3 | **Runner-up**, about -34. Not
taken: smaller, and a second mechanism (⛔ no stitching).
`attemptWithoutPoisoning`, which it calls, is shared with the autonumber
module and stays. |
| `migrateMysqlDatetimeColumns` -39, `migrateMysqlTimeColumns` -32 | 1 /
1 | | | Pinned: each wraps a vocabulary callee in a catch that logs
through `logDurabilityFailure`, which `check:durability-log-level`
resolves within one file only (cut 12). |
| Filter helpers remainder (largest `presentReadValue` -29) | | | |
Below -30 per mechanism; the order says not to stitch them.
`compileFilters` (-75) is refused (inferred return type). |
| `Internal helpers` tenant members (`auditMissingTenant` -26,
`applyTenantScope` -25) | | | | Not taken: `applyTenantScope` holds 2 of
the file's 4 D8 predicates (series limit); `auditMissingTenant` is below
-30 alone. |
| Window function builder (`buildWindowFunction`) -28, `orderKeysFor`
-27, `ensureDatabaseExists` -24, `installQueryTiming` -20 | 1 each | | |
Below -30 each. |
| Column creation members reading private statics
(`explainUnkeyableTextColumn` -83, `explainHashShadowDuplicate` -66,
`createHashShadowUniqueIndex` -62, …), `ensureSequencesTable` -41 | | |
| Series limits: private statics stay; `ensureSequencesTable` writes
`this`. |
## Why
### Why this area, as one area
- **One mechanism.** One method answers one question: "what SQL
expression does this dialect group a date field by at this granularity".
Its two callers and every member it reads stay in the class.
- **It pays the most of any single mechanism that moves cleanly** (-39
measured, against about -34 for the runner-up).
- **No series limit is touched.** The body builds through no
`getBuilder`, reads no static, has no `this.FIELD.delete/insert/update(`
site, uses no `super` or bare `this`, and assigns nothing to `this`. The
method is protected with an annotated return type (`{ sql: string;
bindings: any[] } | null`). `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 body and 0 in the module.
- **Durability gate.** The body has no `try` and calls no
`logDurabilityFailure`. `check:durability-log-level --list` prints 165
lines at both ends, identical except that two `runWideningAlters` seams
in `sql-driver.ts` move 39 lines up and `logDurabilityFailure`'s line 3
down (the import).
- **Subclasses and spies.** `TursoDriver` overrides neither the method
nor a member it reads. `SqliteWasmDriver` overrides the `isSqlite`
getter; the host reads `isSqlite` through a getter on the driver at call
time, so the override is still the one the body reads, and
`sqlite-wasm-driver-date-bucket.test.ts` (in the wasm suite above) pins
the SQL that driver emits. `turso-driver.ts` names
`SqlDriver.buildDateBucketExpr` in prose, still true. The dogfood
`date-bucket-parity-turso.test.ts` redefines `buildDateBucketExpr` on an
instance and `sql-driver-temporal-dialect.test.ts` calls it through `(d
as any)`; both still reach the method, which is still on the class.
- **Path readers, screened.** No script, test, doc or ADR names the
member by a `sql-driver.ts#…` pointer or a `sql-driver.ts::…` key, and
no `scripts/adr-anchors/**` record names it or date bucketing.
## The shape (#23050 shape B, as cuts 1-19 apply it)
- The class method keeps its docblock and signature, byte-identical. Its
body is now one host literal plus `buildDateBucketExpr.call(host, field,
granularity, table)`, marked `[#25521 cut 20]`. The method is
synchronous at both ends, so a failure is still a synchronous throw
(probe reading 7).
- The fields go as GETTERS that read the driver at call time, and the
methods as closures that call them on the driver at call time. So a
subclass override, an instance spy, or a getter overridden in a subclass
is still the one the body reaches (probe readings 3, 4, 5).
- **Comments.** The module header says what moved, what stayed and how
the body reaches the class. The `sql-driver.ts` import comment names cut
20 in 2 lines. Neither cites an `ADR-NNNN` letter. The method's docblock
(which cites ADR-0053) stays in `sql-driver.ts`.
- **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 **1900** decision-letter
citations at base `6845035c6b` (a clean detached worktree) and **1900**
at the move commit, over 91 anchored files at both ends; the two outputs
are byte-identical. Both runs exit 0.
- **Why equal.** No comment inside the moved body or the new header
cites a decision letter, and the module is not anchored.
- **No entry needs a new home.** No anchor entry names the moved member.
`check:adr-symbol-anchors` output is byte-identical at both ends.
- **After `main` moved.** `main` moved 20 commits under the cut (to
`07d18e692`, none in `packages/drivers/**`). Its tip counts **1900**
letters (a clean detached worktree), and so does a local, unpushed merge
of the move commit with it; both exit 0. I did not merge `main` into
this branch: `git merge-tree --write-tree` of the head with it exits 0,
so the tree is not stale.
### 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` into this
worktree and removes the new module, under an EXIT/INT/TERM trap that
restores HEAD. The restore is proved by the HEAD blob hashes, an empty
`git diff HEAD` and 0 status entries (`RESTORE-OK fb5f2d3…
0bb2cca…`).
- **The hashes.** The raw sha256 of `dist/index.d.ts` and
`dist/index.d.mts` is the same at base and at the move commit:
`0f33bf3febaac3c7aa96f68a4226d752766b8203ab7acade523b69f9aaa44d74`
(unchanged since cut 8). These two are the dist's only declaration files
(no chunk), so the declaration-reorder bar of ruling `6441032442` does
not come into play.
- **Positive control.** I dropped `protected` from `buildDateBucketExpr`
in a copy of the head `index.d.ts` (1 hit, then 0). The copy hashes to
`1fda05673f202a32293501dc46b90afa75edd56c1dc632f66d4699af09ef3197`, with
`cmp` exit 1.
- **Export lists.** CJS `require` of each dist gives 59 names (sha1
`05757ce5ae` at both ends); the ESM namespace of `index.mjs` gives the
same 59 at both ends (sha1 `05757ce5ae`). Neither the moved function nor
`DateBucketHost` is among them.
- **The head dist carries the move.** `.call(host` sites in `index.mjs`
go from 69 at base to 70 at head (the stub).
### Move-only proof
The proof compares TypeScript compiler AST leaf tokens (JSDoc nodes
skipped), base `6845035c6b` against the move commit `7c6f6f1fe`. It is a
scratch script and is not committed.
| Moved body | Body tokens | Comments | Parameter tokens less `this` |
Return type tokens | Body lines |
|:--|--:|--:|--:|--:|--:|
| `buildDateBucketExpr` | 423 | 11 | 20 | 13 | 56 |
- **The moved body.** 0 tokens differ and every comment is identical.
Each body line is the base line less two leading spaces. It is not
`async` at either end.
- **The stub.** 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 349 unmoved members are byte-identical, trivia included.
- **Top level of `sql-driver.ts`.** 179 of 180 base statements are
byte-identical; the other is the class. The head adds one statement, the
new import (its 2-line comment is its leading trivia).
- **Result.** `PROOF OK`, exit 0.
- **Negative control.** Through `scripts/ablation-replace.mjs`, I
changed `'%x-W%v'` to `'%x-W%V'` in the module's MySQL `week` arm
(anchor 1 hit, then 0, checked on disk). The proof then reports
`buildDateBucketExpr` as differing, prints `PROOF FAILED`, and exits 1.
The restore was proved (blob `0bb2ccab65` 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 `6845035c6b` against the move commit `7c6f6f1fe`. Every part's exit
code was captured on its own (build, probe, three suites: all 0 at both
legs).
| Suite | Base | Head | Lost / changed / added |
|:--|:--|:--|:--|
| `@objectstack/driver-sql` | 4061 (3847 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 on
the move commit. `pnpm exec eslint --no-inline-config
packages/drivers/driver-sql` exits 0 (driver-sql has no `lint` script of
its own).
- **Late-binding probe.** A scratch script, not committed. It runs node
against each end's built dist and prints 344 readings, each with the
result or the error's class, message and top stack frame:
1. `buildDateBucketExpr` on SQLite, PostgreSQL, MySQL and MSSQL drivers
(never connected), for all five granularities plus `hour` and none, over
a declared `date`, `datetime`, `time` and `text` field, an undeclared
field, and no / an unknown table;
2. the SQLite legacy-datetime repair arm (`sqliteTemporalArg`'s other
branch);
3. a SUBCLASS overriding the `isSqlite` / `isPostgres` getters, and one
overriding `dateGranularityCapabilities` (the overrides are the ones
read);
4. subclass overrides of `temporalFieldKind` (PostgreSQL, MySQL) and of
`sqliteTemporalArg` (likewise);
5. instance spies on `temporalFieldKind` and `sqliteTemporalArg` (they
are the ones the body reaches, with the arguments recorded);
6. `knex` replaced on the instance after construction, then restored;
7. a failure inside the body (a throwing `temporalFieldKind`; an
undefined capability row): synchronous throws;
8. the callers: `dateBucketSql` on three dialects, and real SQLite
`aggregate` GROUP BYs over a `date` and a `datetime` field at all five
granularities;
9. the method's shape on the prototype (type, arity).
- **Probe result.** 343 of the 344 readings are identical. The other one
is reading 7's undefined capability row, which differs only in the top
stack frame's receiver name: `NullCaps.buildDateBucketExpr` at base and
`Object.buildDateBucketExpr` at head. That is shape B's receiver, the
same at every earlier cut, and no test or consumer reads it.
- **Not run.** No ablation, because no tested behaviour changed.
- **`test:repo`.** Not run locally; it is CI's run on this PR.
### Gates
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives **48** families for this diff (the
same 48 cuts 17-19 derived). I ran each one on its own and captured its
exit code before any pipe, after a full `pnpm build` of the move commit
(116 of 116 tasks).
- **Move commit `7c6f6f1fe`: 48 run, all 48 exit 0.** `--ran`
reconciles: `48 derived famil(ies) accounted for — 48 run, 0
NOT-MEASURED`, exit 0. (I fetched the pinned fixture commit of
`check-plugin-teardown-shape.mjs --self-test` into this shallow clone
first.)
- **Hand gates, all exit 0:** `check-adr-anchors`,
`check-adr-symbol-anchors`, `check-tenant-audit-census`,
`check-platform-checklist --changed-from origin/main`,
`check-commit-card-trailers --range origin/main..HEAD`, `eslint
--no-inline-config packages/drivers/driver-sql`,
`check-durability-degradation-log-level --list`. In a clean detached
worktree at base `6845035c6b` and on the move commit,
`check-adr-anchors`, `check-adr-symbol-anchors` and
`check-tenant-audit-census` print byte-identical output;
`check-object-def-param-keys` differs only in its file count (3388 to
3389, the new module); `check-durability-degradation-log-level --list`
prints the same 165 lines, line numbers aside.
- **No gate silently empty.** Each derived gate's log prints a non-zero
population (for example `check:object-def-param-keys` compares 7
override parameter positions over 3389 files with every control firing;
`check:tenant-chokepoint` reads 24 `getBuilder()` bindings across 3
files; `check:durability-log-level` reads 89 read seams;
`check:dual-build-cjs-loads` loads 112 entry points across 69 packages;
`check:driver-conformance` scores 11 of 11 dialect-scored cells).
The 48 derived commands: `node
scripts/check-closing-keyword-parity.mjs`, `node
scripts/check-closing-keyword-parity.mjs --self-test`, `node
scripts/check-comment-mask-adoption.mjs`, `node
scripts/check-comment-mask-adoption.mjs --self-test`, `node
scripts/check-comment-mask-corpus.mjs`, `node
scripts/check-dts-emitted.mjs --self-test`, `node
scripts/check-issue-citations.mjs`, `node
scripts/check-plugin-teardown-shape.mjs`, `node
scripts/check-plugin-teardown-shape.mjs --self-test`, `node
scripts/ci/assert-turbo-remote-cache.mjs --self-test`, `node
scripts/ci/plan-test-core-shards.mjs --self-test`, `node
scripts/ci/prune-turbo-cache.mjs --self-test`, `node
scripts/docs-audit/check-affected-docs.mjs`, `node
scripts/docs-audit/check-drift-comment.mjs`, `pnpm --filter
@objectstack/spec run check:duration-unit-keys`, `pnpm
check:ci-filter-parity`, `pnpm check:closed-ceremony-text`, `pnpm
check:cross-package-test-inputs`, `pnpm
check:dispatcher-error-vocabulary`, `pnpm check:doc-authoring`, `pnpm
check:driver-conformance`, `pnpm check:driver-memory-census`, `pnpm
check:dts-closure`, `pnpm check:dual-build-cjs-loads`, `pnpm
check:durability-log-level`, `pnpm check:error-status-conformance`,
`pnpm check:gitlink-declared`, `pnpm check:issue-citations`, `pnpm
check:keyed-text-bounds`, `pnpm check:lean-entry-closure`, `pnpm
check:logger-receiver-detach`, `pnpm check:nul-bytes`, `pnpm
check:object-def-param-keys`, `pnpm check:org-identifier`, `pnpm
check:page-declaration-shape`, `pnpm
check:platform-object-tenancy-census`, `pnpm check:published-files`,
`pnpm check:refd-timer-probe`, `pnpm check:registry-log-declared`, `pnpm
check:rest-log-spy-declared`, `pnpm check:slot-lookup`, `pnpm
check:sourcemap-no-sources-content`, `pnpm check:system-context-census`,
`pnpm check:tenant-chokepoint`, `pnpm check:test-source-alias`, `pnpm
check:tier-file-adoption`, `pnpm check:undeclared-dep-imports`, `pnpm
check:watch-hint-literal`.
## Acceptance notes
- **`check:tenant-chokepoint`'s `SCAN_FILES` does not list
`sql-driver-date-bucket.ts`.** The moved body holds 0 tenant predicates
and builds no query (it returns `{ sql, bindings }` text). Noted, not
filed: widening `SCAN_FILES` would be a gate change.
- **Stale links.** `sql-driver.ts` has the same 30 `{@link X}` sites (21
names) that are neither a top-level binding nor a `SqlDriver` member at
base and at head (the name set is identical). The module has none.
- **The series' remaining yield, priced on this base.** After this cut,
one single mechanism still pays more than -30: the presumed-timestamp
update (`updateWithPresumedTimestamp` with
`resolveUpdatedAtColumnPresence`, -37 in bodies, about -34 with a new
module's import). Everything else is -29 or less per mechanism, or
pinned or blocked by a series limit (the MySQL widenings, the tenant
members, the private-static readers).
## Human Minimum
- [x] 1. No `packages/spec` change.
- [x] 2. One new name, `DateBucketHost`, in a new module that `index.ts`
does not re-export.
- [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_01FEkQ5pPv99puvEK3Nmm1Mc)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5pPv99puvEK3Nmm1Mc
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 24351cf commit 80064b2
2 files changed
Lines changed: 136 additions & 56 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
192 | 192 | | |
193 | 193 | | |
194 | 194 | | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
195 | 198 | | |
196 | 199 | | |
197 | 200 | | |
| |||
5075 | 5078 | | |
5076 | 5079 | | |
5077 | 5080 | | |
5078 | | - | |
5079 | | - | |
5080 | | - | |
5081 | | - | |
5082 | | - | |
5083 | | - | |
5084 | | - | |
5085 | | - | |
5086 | | - | |
5087 | | - | |
5088 | | - | |
5089 | | - | |
5090 | | - | |
5091 | | - | |
5092 | | - | |
5093 | | - | |
5094 | | - | |
5095 | | - | |
5096 | | - | |
5097 | | - | |
5098 | | - | |
5099 | | - | |
5100 | | - | |
5101 | | - | |
5102 | | - | |
5103 | | - | |
5104 | | - | |
5105 | | - | |
5106 | | - | |
5107 | | - | |
5108 | | - | |
5109 | | - | |
5110 | | - | |
5111 | | - | |
5112 | | - | |
5113 | | - | |
5114 | | - | |
5115 | | - | |
5116 | | - | |
5117 | | - | |
5118 | | - | |
5119 | | - | |
5120 | | - | |
5121 | | - | |
5122 | | - | |
5123 | | - | |
5124 | | - | |
5125 | | - | |
5126 | | - | |
5127 | | - | |
5128 | | - | |
5129 | | - | |
5130 | | - | |
5131 | | - | |
5132 | | - | |
5133 | | - | |
| 5081 | + | |
| 5082 | + | |
| 5083 | + | |
| 5084 | + | |
| 5085 | + | |
| 5086 | + | |
| 5087 | + | |
| 5088 | + | |
| 5089 | + | |
| 5090 | + | |
| 5091 | + | |
| 5092 | + | |
| 5093 | + | |
| 5094 | + | |
5134 | 5095 | | |
5135 | 5096 | | |
5136 | 5097 | | |
| |||
0 commit comments