From 286316ebdea3325aaacd78a197013a591792dbcd Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 06:15:49 +0000 Subject: [PATCH 1/2] docs(driver-sql): re-anchor the dead tracker citations to the commits and ADR that decided them (stage 4 of #20595) Comment and docblock prose only, in ruling C+D's form C: every comment site in packages/drivers/driver-sql that cited a tracker number answering 404 (39 numbers, 291 sites on 287 lines), plus the dead comment id 5448627494 (2 lines), now cites the ADR when one records the decision, otherwise the commit in this repository that made it. Every file keeps its line count; no code token, string literal or numeric literal moves; no tracker number is added. Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude --- .../src/builtin-column-collision.ts | 2 +- .../src/dialect-emission-refusal.ts | 2 +- .../src/live-dialect-matrix.testkit.ts | 2 +- .../src/media-column-move.pin.test.ts | 2 +- .../driver-sql/src/media-column-move.ts | 2 +- .../schema-drift.base-type-mismatch.test.ts | 2 +- .../drivers/driver-sql/src/schema-drift.ts | 34 +-- ...er-11176-bulk-and-merge-updated-at.test.ts | 16 +- ...river-11224-update-stamp-precision.test.ts | 2 +- .../sql-driver-11627-hash-shadow-key.test.ts | 2 +- ...er-11635-boolean-aggregand-answers.test.ts | 4 +- ...1782-boolean-row-read-presentation.test.ts | 4 +- ...-driver-11794-richtext-text-family.test.ts | 12 +- .../sql-driver-12380-json-roundtrip.test.ts | 12 +- ...-driver-12998-shadow-null-safe-key.test.ts | 6 +- ...sql-driver-12999-stale-text-remedy.test.ts | 6 +- ...r-13015-shadow-carried-index-drift.test.ts | 16 +- ...13056-orphan-shadow-column-cleanup.test.ts | 8 +- ...-federated-missing-remote-envelope.test.ts | 8 +- ...iver-13973-canonical-iso-read-door.test.ts | 8 +- ...2-plain-unique-duplicate-preflight.test.ts | 2 +- ...479-shadow-plain-unique-duplicates.test.ts | 8 +- ...-15683-temporal-text-operator-gate.test.ts | 2 +- .../sql-driver-15989-file-column-move.test.ts | 4 +- ...l-driver-15989-file-family-bare-id.test.ts | 2 +- ...r-16570-init-objects-indexes-param.test.ts | 2 +- ...r-16657-operator-facing-cause-text.test.ts | 2 +- ...driver-16711-object-def-param-keys.test.ts | 10 +- ...43-multi-valued-boolean-membership.test.ts | 18 +- ...ulti-valued-boolean-read-inversion.test.ts | 16 +- ...river-17590-json-column-membership.test.ts | 8 +- ...iver-17639-distinct-fault-envelope.test.ts | 20 +- ...stinct-unresolvable-column-refusal.test.ts | 16 +- ...-driver-20987-json-membership-move.test.ts | 4 +- .../sql-driver-backend-fault-envelope.test.ts | 2 +- .../sql-driver-datetime-mysql-storage.test.ts | 2 +- .../sql-driver-deferred-ddl-lock-wait.test.ts | 12 +- .../sql-driver-diagnostic-value-probe.test.ts | 6 +- ...l-driver-distinct-filter-narrowing.test.ts | 8 +- .../sql-driver-doors-declared-types.test.ts | 16 +- .../sql-driver-external-remote-name.test.ts | 2 +- ...l-driver-json-backfill-depth-limit.test.ts | 6 +- ...river-json-column-operator-refusal.test.ts | 2 +- .../src/sql-driver-keyed-text-mysql.test.ts | 4 +- .../src/sql-driver-query-signature.test.ts | 6 +- .../sql-driver-shard-tenancy-opt-out.test.ts | 2 +- .../src/sql-driver-tenant-scope.test.ts | 4 +- .../sql-driver-timestamps-without-ddl.test.ts | 2 +- ...-driver-ttl-onlywhen-null-dialects.test.ts | 6 +- ...-driver-unique-violation-predicate.test.ts | 8 +- .../sql-driver-update-declared-null.test.ts | 10 +- ...driver-value-roundtrip-conformance.test.ts | 8 +- .../sql-driver-window-function-output.test.ts | 8 +- .../drivers/driver-sql/src/sql-driver.test.ts | 2 +- packages/drivers/driver-sql/src/sql-driver.ts | 202 +++++++++--------- 55 files changed, 291 insertions(+), 291 deletions(-) diff --git a/packages/drivers/driver-sql/src/builtin-column-collision.ts b/packages/drivers/driver-sql/src/builtin-column-collision.ts index 288f3157502..86ebb324c1b 100644 --- a/packages/drivers/driver-sql/src/builtin-column-collision.ts +++ b/packages/drivers/driver-sql/src/builtin-column-collision.ts @@ -72,7 +72,7 @@ export type FieldKeyClass = 'storage' | 'presentation'; export const FIELD_KEY_STORAGE_CLASS: Readonly> = Object.freeze({ // ---- storage: the column's own shape ------------------------------------- type: 'storage', // `createColumn`: the column type itself - maxLength: 'storage', // `createColumn`: varchar(n) vs TEXT, and the #11374 keyable decision + maxLength: 'storage', // `createColumn`: varchar(n) vs TEXT, and commit d0e3a885b's keyable decision multiple: 'storage', // `createColumn`: a multi-value field is a JSON column precision: 'storage', // numeric column shape (this driver does not read it yet) scale: 'storage', // numeric column shape (this driver does not read it yet) diff --git a/packages/drivers/driver-sql/src/dialect-emission-refusal.ts b/packages/drivers/driver-sql/src/dialect-emission-refusal.ts index 00278ef8bf7..b87422bb1a1 100644 --- a/packages/drivers/driver-sql/src/dialect-emission-refusal.ts +++ b/packages/drivers/driver-sql/src/dialect-emission-refusal.ts @@ -63,7 +63,7 @@ * `engine.syncObjectSchema` → `SqlDriver.syncSchema` → the DDL gate, on a * server that is already serving HTTP. That was the exact test #8035 applied * when it UNregistered `MONGODB_MULTI_TENANT_UNSUPPORTED` for failing it — a - * removal #16649 reversed under the #16404 door-or-no-door rule, which takes + * removal that commit 613bfbd3d reversed under the #16404 door-or-no-door rule, which takes * registration out of that test's reach entirely: every `code` that ships in * `dist` carries a ledger row, and wire-reachability now decides only what a * door ANSWERS with. This one can be carried, so the door serves it under its diff --git a/packages/drivers/driver-sql/src/live-dialect-matrix.testkit.ts b/packages/drivers/driver-sql/src/live-dialect-matrix.testkit.ts index 612ba447ad3..33691dd1eb0 100644 --- a/packages/drivers/driver-sql/src/live-dialect-matrix.testkit.ts +++ b/packages/drivers/driver-sql/src/live-dialect-matrix.testkit.ts @@ -448,7 +448,7 @@ export function declareUnprovisionedCell(cell: DialectCell, matrix: string): voi * Nothing in the corridor (15_000, 600_000) is distinguishable by measurement, * so the value is fixed by this package's OWN existing answer for live-touching * sites: 60 explicit `60_000` budgets across 22 files — #13688 and its sweep - * #13902 put them on live test BODIES, #14213 and #14628 on the hooks that pay + * #13902 put them on live test BODIES, #14213 and commit 6392b9c2b on the hooks that pay * a live connect. Adopting it leaves the live matrix with ONE live budget * instead of two, so a red at 60_000 ms is unambiguous about which bound it hit. * diff --git a/packages/drivers/driver-sql/src/media-column-move.pin.test.ts b/packages/drivers/driver-sql/src/media-column-move.pin.test.ts index bc5c696187c..bf5f6a51429 100644 --- a/packages/drivers/driver-sql/src/media-column-move.pin.test.ts +++ b/packages/drivers/driver-sql/src/media-column-move.pin.test.ts @@ -11,7 +11,7 @@ * refusing. * * ⛔ The single most load-bearing assertion here is that the PostgreSQL retype - * arm's pre-check exists at all. The #15041 addendum prescribed the retype with + * arm's pre-check exists at all. The ADR-0104 2026-09-05 addendum prescribed the retype with * NO pre-check, and that form was measured on live PostgreSQL 16.13 to accept a * row holding an inline metadata blob and flatten it to its own literal text. * The director ruling (decision batch #120 item 1) replaced the clause; a pin diff --git a/packages/drivers/driver-sql/src/media-column-move.ts b/packages/drivers/driver-sql/src/media-column-move.ts index b63b7d804e1..fe0ce2c4d5b 100644 --- a/packages/drivers/driver-sql/src/media-column-move.ts +++ b/packages/drivers/driver-sql/src/media-column-move.ts @@ -6,7 +6,7 @@ * `sys_file` id, and the pre-check that ABORTS instead of destroying a row the * backfill never converted. * - * The ruling on #15041 gave this step one requirement in words — abort *"on + * The ruling in ADR-0104's 2026-09-05 addendum gave this step one requirement in words — abort *"on * the first cell that is not a JSON string"* — and one sketch in SQL beside * it. **The sketch does not implement the requirement, and that was measured * rather than argued** (director ruling, decision batch #120 item 1): on live diff --git a/packages/drivers/driver-sql/src/schema-drift.base-type-mismatch.test.ts b/packages/drivers/driver-sql/src/schema-drift.base-type-mismatch.test.ts index 86dd18df4f5..dc8eb8acfe9 100644 --- a/packages/drivers/driver-sql/src/schema-drift.base-type-mismatch.test.ts +++ b/packages/drivers/driver-sql/src/schema-drift.base-type-mismatch.test.ts @@ -364,7 +364,7 @@ describe('diffManagedTable — a SINGLE-VALUE JSON-class field over a stale text // The card's scope, asserted rather than described: the fork applies to // every single-value member of the writer's set. // - // ⚠️ [#15989] #15041 has since been ruled — option A, the file family's + // ⚠️ [#15989] ADR-0104's 2026-09-05 addendum has since ruled — option A, the file family's // column holds the bare `sys_file` id — so the family is no longer a member // of {@link JSON_COLUMN_FIELD_TYPES}: it is asked per deployment, and // `diffTags` omits `fileColumnsMoved`, i.e. every call here is about a diff --git a/packages/drivers/driver-sql/src/schema-drift.ts b/packages/drivers/driver-sql/src/schema-drift.ts index 86bed97c965..72e45a83968 100644 --- a/packages/drivers/driver-sql/src/schema-drift.ts +++ b/packages/drivers/driver-sql/src/schema-drift.ts @@ -417,7 +417,7 @@ export const HASH_SHADOW_SUFFIX = '__hash'; * orphan pass reports as `unmapped_column` with a `drop_column` op. Dropping it * would take the UNIQUE index it carries with it, silently returning the object * to "registered but its declared uniqueness unenforced" — the very state - * #11374/#11627 exist to end, reached this time through the migration tool + * #11627 and commit d0e3a885b exist to end, reached this time through the migration tool * rather than through a refused DDL. * * Matched by SUFFIX rather than by a registry of known names, deliberately: the @@ -448,7 +448,7 @@ export function isHashShadowColumn(name: string): boolean { * 64-character identifier limit. * * ⚠️ Lives HERE, beside {@link isHashShadowColumn}, rather than in the driver: - * #13015 was the price of the split. The ORPHAN-column pass knew the shadow + * The defect commit cd1348802 fixed was the price of the split. The ORPHAN-column pass knew the shadow * vocabulary and the INDEX differ did not, so a healthy shadow-carried UNIQUE * had its column protected from a drop while the index that column carries was * proposed for a destructive rebuild. Both passes now ask the same module the @@ -473,7 +473,7 @@ export function hashShadowColumnFor(indexName: string): string { /** * One key part a hash shadow hashes: the column identity, and whether the * generation expression folds it through the NULL-safe `COALESCE(col, ...)` - * form (ADR-0120 D3, carried into the shadow by #12998). + * form (ADR-0120 D3, carried into the shadow by commit df1c75c4b). */ export interface HashShadowKeyPart { column: string; @@ -482,16 +482,16 @@ export interface HashShadowKeyPart { /** * Read the DECLARED key parts back out of a hash shadow's stored - * `GENERATION_EXPRESSION` (#13015). + * `GENERATION_EXPRESSION` (commit cd1348802). * * This is what makes a shadow-carried key COMPARABLE rather than merely - * skippable. Since #12998 the expression carries the NULL-safe parts in their + * skippable. Since commit df1c75c4b the expression carries the NULL-safe parts in their * COALESCE spelling, so the FORM of the key — which columns, and which of them * are folded — survives the round trip, and the differ can ask the real * question ("does this shadow enforce what metadata declares?") instead of the * blind one ("is this a shadow at all?"). * - * ⛔ Why the blind question is not good enough: a shadow created BEFORE #12998 + * ⛔ Why the blind question is not good enough: a shadow created BEFORE commit df1c75c4b * hashes the RAW columns, so `CONCAT` returns NULL for every NULL-organization * row and the rows the COALESCE bucket exists to constrain are constrained by * nothing (#5030's shape). It is indistinguishable BY NAME from a healthy one. @@ -858,7 +858,7 @@ export function diffManagedTable(args: { columns: PhysicalColumn[]; dialect: SqlDialectName; /** - * Which columns an index KEYS ON (#11374), keyed by field name — the exact + * Which columns an index KEYS ON (commit d0e3a885b), keyed by field name — the exact * map {@link indexedKeyColumns} builds. Consulted ONLY by the varchar-length * branch below, through {@link varcharColumnChars}, to answer the same * question `createColumn` asks before it sizes a text-family column. @@ -1703,7 +1703,7 @@ export interface PhysicalIndex { /** * When this index is physically carried by a #11627 hash shadow, the * DECLARED key parts that shadow hashes, read back from the generation - * expression (#13015 via #12998) by `SqlDriver.introspectIndexes`. + * expression (commit cd1348802 via commit df1c75c4b) by `SqlDriver.introspectIndexes`. * * Absent both when the index is NOT shadow-carried and when it is but the * expression could not be read. {@link isHashShadowCarrier} tells those two @@ -2029,7 +2029,7 @@ export function diffUnbuildableIndexes(args: { * field-level `unique` through {@link uniqueIndexesFromFields}, object-level * `indexes[]` through {@link normalizeDeclaredIndex} — so "which columns end up * in a key" has ONE answer, shared by the index sync that creates them and by - * the DDL that has to make them keyable in the first place (#11374). + * the DDL that has to make them keyable in the first place (commit d0e3a885b). * * ⚠️ Deliberately NOT filtered by `physicalColumns`, unlike `expectedIndexes`: * its caller runs BEFORE the columns exist — deciding a column's TYPE is the @@ -2275,7 +2275,7 @@ function indexSignature( * Answerable from the index alone, by NAME: the shadow is derived from the * index name ({@link hashShadowColumnFor}), so a carrier is an index whose sole * key column is its own shadow. That is what makes this the FAIL-SAFE half of - * #13015 — it holds even when the generation expression cannot be read, and a + * commit cd1348802 — it holds even when the generation expression cannot be read, and a * carrier is never a thing this differ may propose destroying on a guess. */ export function isHashShadowCarrier(index: PhysicalIndex): boolean { @@ -2283,7 +2283,7 @@ export function isHashShadowCarrier(index: PhysicalIndex): boolean { } /** - * The key an index ENFORCES, which is not always the key it STORES (#13015). + * The key an index ENFORCES, which is not always the key it STORES (commit cd1348802). * * For an ordinary index the two are the same. For a #11627 shadow-carried * UNIQUE the stored key is one VARBINARY(32) generated column and the enforced @@ -2358,7 +2358,7 @@ export function diffManagedIndexes(args: { if (!p || p.primary || isRuntimeManagedIndex(p, runtimeCreated, tenantField)) return false; if (!p.unique || p.partial === true) return false; if ((p.expressions?.length ?? 0) > 0 || (p.nullSafeColumns?.length ?? 0) > 0) return false; - // #13015: nor is a hash-shadow carrier. Its stored key is one generated + // Commit cd1348802: nor is a hash-shadow carrier. Its stored key is one generated // column, so the identity comparison below already excludes it — stated // outright because the exclusion must survive that comparison changing, // and because `replace_unique_index` DROPS the legacy name. @@ -2428,7 +2428,7 @@ export function diffManagedIndexes(args: { // Same normalization on BOTH sides (#4884, ADR-0120 D3): column identity // AND key-part form, literal-agnostic on the COALESCE literal — asked of // the key the index ENFORCES, which for a #11627 shadow-carried UNIQUE is - // not the column it stores (#13015). + // not the column it stores (commit cd1348802). const pk = enforcedIndexKey(p); if ( p.unique === e.unique && @@ -2445,7 +2445,7 @@ export function diffManagedIndexes(args: { // (`recreate_index` → drop first) this differ cannot undo. Not ours to // reconcile (#4884). if (isRuntimeManagedIndex(p, runtimeCreated, tenantField)) continue; - // #13015, fail-safe half: a hash-shadow carrier whose generation + // Commit cd1348802, fail-safe half: a hash-shadow carrier whose generation // expression could NOT be read (`shadowKey` unresolved). We know by name // that the index is driver-owned and that its stored key is a digest, so // the identity comparison above is meaningless for it — but we do not know @@ -2455,7 +2455,7 @@ export function diffManagedIndexes(args: { // ⛔ The `!p.shadowKey` half is load-bearing, and was measured: without it // this guard swallows the RESOLVED carriers too, which silently demotes the // whole fix to the blind skip — every shadow-carried index unreportable, - // including a pre-#12998 one hashing the RAW columns whose constraint does + // including one from before commit df1c75c4b hashing the RAW columns whose constraint does // not cover NULL-organization rows at all. Green, quiet, and the exact // trade this fix exists to refuse. if (isHashShadowCarrier(p) && !p.shadowKey) continue; @@ -2471,7 +2471,7 @@ export function diffManagedIndexes(args: { // clean → recategorised `safe` (dev autoMigrate may apply); duplicates → // blocked with a row report, the old index left in place. // - // #13015: read through the ENFORCED key, so a pre-#12998 shadow — same + // Commit cd1348802: read through the ENFORCED key, so a shadow from before commit df1c75c4b — same // columns, hashed RAW instead of through the NULL-safe COALESCE — is // recognised as exactly this tightening and gets the same duplicate // pre-flight before anything is dropped. The explicit "physical side is @@ -2530,7 +2530,7 @@ export function diffManagedIndexes(args: { // (#4884 — the boot advised dropping `idx_sys_metadata_overlay_draft`, the // partial UNIQUE enforcing draft-overlay uniqueness, on a healthy fresh DB). if (isRuntimeManagedIndex(p, runtimeCreated, tenantField)) continue; - // #13015: an orphaned shadow carrier is still an orphan — its declaration + // Commit cd1348802: an orphaned shadow carrier is still an orphan — its declaration // is gone, and `drop_index` is the right remedy — but the report must name // the constraint it enforced, not the digest column it stored. const po = enforcedIndexKey(p); diff --git a/packages/drivers/driver-sql/src/sql-driver-11176-bulk-and-merge-updated-at.test.ts b/packages/drivers/driver-sql/src/sql-driver-11176-bulk-and-merge-updated-at.test.ts index 098aef7f709..88c2a09085e 100644 --- a/packages/drivers/driver-sql/src/sql-driver-11176-bulk-and-merge-updated-at.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-11176-bulk-and-merge-updated-at.test.ts @@ -4,9 +4,9 @@ * [#11176] The two write doors that did not advance `updated_at`: `updateMany()` * on every dialect, and `upsert()`'s merge branch on Postgres and MySQL. * - * ## Not #11067, and the difference is what this file is set up to show + * ## Not the defect commit 479fba50d fixed, and the difference is what this file is set up to show * - * #11067 is about `tablesWithTimestamps` being filled only by DDL, so a + * Commit 479fba50d is about `tablesWithTimestamps` being filled only by DDL, so a * `skipSchemaSync` deployment never stamped. These two are missing on EVERY * deployment — so almost every table here is built by the driver's own * `initObjects`, with `tablesWithTimestamps` correctly populated. That is the @@ -57,7 +57,7 @@ * ## §6 The narrowing, stated as a measurement rather than a claim * * The upsert stamp reads `observedUpdatedAtColumn` — DDL-observed, or settled - * `present` by a successful stamped UPDATE — and deliberately NOT #11067's + * `present` by a successful stamped UPDATE — and deliberately NOT commit 479fba50d's * `presumed` state. `presumed` exists so an UPDATE can speculate and then * RECOVER (`updateWithPresumedTimestamp`); the upsert door has no such recovery, * and a wrong presumption there would name a missing column in an INSERT column @@ -66,7 +66,7 @@ * would break first if the narrowing were ever widened without a recovery. * * `updateMany` has no such narrowing: it is an UPDATE door, so it reuses - * #11067's machinery whole (§7). + * commit 479fba50d's machinery whole (§7). * * ## Reverse verification (direction predicted before running) * @@ -87,7 +87,7 @@ const OPTS = { bypassTenantAudit: true } as any; /** * The instant a row is backdated to before the write under test. * - * A sentinel far in the past rather than a sleep, for #11067's reason: a stamp + * A sentinel far in the past rather than a sleep, for commit 479fba50d's reason: a stamp * taken a moment after an insert default can legitimately land on the same * stored value. Backdating removes the race without weakening the assertion — * the stamp either moved to ~now or did not move at all, and those are six @@ -338,7 +338,7 @@ function measure(cell: DialectCell): void { // ── §6 The declared narrowing, measured at the property that would break ── it('§6 still upserts a hand-migrated table that has NO `updated_at` column', async () => { - // The upsert stamp reads the OBSERVED answer, never #11067's presumption, + // The upsert stamp reads the OBSERVED answer, never commit 479fba50d's presumption, // because this door has no recovery to fall back on. If that narrowing is // ever widened without one, this is the call that stops working. const id = 'n1'; @@ -349,7 +349,7 @@ function measure(cell: DialectCell): void { expect(after.row.title).toBe('b'); }); - // ── §7 `updateMany` reuses #11067's machinery whole ────────────────────── + // ── §7 `updateMany` reuses commit 479fba50d's machinery whole ────────────────────── it('§7 stamps a `skipSchemaSync` table, and still updates one without the column', async () => { // The presumption and its recovery, exercised through the bulk door: it is @@ -363,7 +363,7 @@ function measure(cell: DialectCell): void { expect(presumed.updatedAt).toBeGreaterThan(BACKDATED_MS); expect(presumed.row.title).toBe('b'); - // The other half of #11067's pair: a table that genuinely lacks the column + // The other half of commit 479fba50d's pair: a table that genuinely lacks the column // must NOT gain a new rejection. await driver.create(NO_COL, { id: 'n2', title: 'a', status: 'bulk' }, OPTS); const touched = await driver.updateMany(NO_COL, { where: { status: 'bulk' } }, { title: 'b' }, OPTS); diff --git a/packages/drivers/driver-sql/src/sql-driver-11224-update-stamp-precision.test.ts b/packages/drivers/driver-sql/src/sql-driver-11224-update-stamp-precision.test.ts index 97d7c78d29f..e0413bd8825 100644 --- a/packages/drivers/driver-sql/src/sql-driver-11224-update-stamp-precision.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-11224-update-stamp-precision.test.ts @@ -38,7 +38,7 @@ * audit answer comparing the two, a "modified since creation?" badge, and above * all a millisecond-precision delta cursor (`updated_at > cursor`), which * SKIPS every row whose stamp was truncated back below it — the same - * silent-wrong-answer family as #11067 / #11176 / #11223, reached by a fourth + * silent-wrong-answer family as #11176 / #11223 / the one commit 479fba50d fixed, reached by a fourth * mechanism. §2 asserts that skip is gone by issuing the cursor comparison as * real SQL on the server rather than comparing numbers in JS. * diff --git a/packages/drivers/driver-sql/src/sql-driver-11627-hash-shadow-key.test.ts b/packages/drivers/driver-sql/src/sql-driver-11627-hash-shadow-key.test.ts index d0f8b294462..3b10199f92c 100644 --- a/packages/drivers/driver-sql/src/sql-driver-11627-hash-shadow-key.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-11627-hash-shadow-key.test.ts @@ -15,7 +15,7 @@ * * ## Why a shadow and not a prefix index * - * The maintainer's 2026-08-24 ruling on #11374 chose the hash route and + * The maintainer's 2026-08-24 ruling, landed as commit 107bb4ba4, chose the hash route and * rejected prefix-unique indexes, on measurement: `UNIQUE KEY (token(191))` * enforces uniqueness over the PREFIX, so two genuinely distinct tokens that * share their first 191 characters collide and the second is refused as diff --git a/packages/drivers/driver-sql/src/sql-driver-11635-boolean-aggregand-answers.test.ts b/packages/drivers/driver-sql/src/sql-driver-11635-boolean-aggregand-answers.test.ts index 2cd07a7e305..54f15d5d94b 100644 --- a/packages/drivers/driver-sql/src/sql-driver-11635-boolean-aggregand-answers.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-11635-boolean-aggregand-answers.test.ts @@ -6,7 +6,7 @@ * * ## The ruling this suite pins * - * #11152 (maintainer 2026-08-28, applied in its comment 5448627494, ruling + * #11152 (maintainer 2026-08-28, landed as commit f6fa22ce1, ruling * verbatim and untranslated: 「12745 A回,其他同意。」 — option A on that * card) adopted, superseding #11249's `false`/`true` for the order * statistics: @@ -16,7 +16,7 @@ * — the same numeric domain `sum` / `avg` answer in, so one column's five * aggregates answer in one domain rather than three-numbers-two-booleans. * - **`sum` / `avg` answer arithmetic** (`3` / `0.5` on the 3-true/3-false - * fixture) — the settled #11065 family shape, unchanged. + * fixture) — the settled commit 20950404c family shape, unchanged. * * ## The two measured gaps this suite exists to keep closed * diff --git a/packages/drivers/driver-sql/src/sql-driver-11782-boolean-row-read-presentation.test.ts b/packages/drivers/driver-sql/src/sql-driver-11782-boolean-row-read-presentation.test.ts index 9dd2f87cddb..389171a36f4 100644 --- a/packages/drivers/driver-sql/src/sql-driver-11782-boolean-row-read-presentation.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-11782-boolean-row-read-presentation.test.ts @@ -33,8 +33,8 @@ * * ## [#11152] The `min`/`max` CELLS are superseded — the row-read doors are NOT * - * The maintainer's 2026-08-28 ruling on #11152 (applied in that card's comment - * 5448627494, verbatim 「12745 A回,其他同意。」, superseding #11249) pins that + * The maintainer's 2026-08-28 ruling on #11152 (landed as commit + * f6fa22ce1, verbatim 「12745 A回,其他同意。」, superseding #11249) pins that * **booleans aggregate as numbers on every face**: `min(flag)`/`max(flag)` * answer the JSON NUMBERS `0`/`1`, so the aggregate-result boolean * presentation this suite once asserted is deliberately removed again. ⚠️ diff --git a/packages/drivers/driver-sql/src/sql-driver-11794-richtext-text-family.test.ts b/packages/drivers/driver-sql/src/sql-driver-11794-richtext-text-family.test.ts index e1519cb2dce..1ffc7107357 100644 --- a/packages/drivers/driver-sql/src/sql-driver-11794-richtext-text-family.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-11794-richtext-text-family.test.ts @@ -39,7 +39,7 @@ * their declared bound and the invariant above licenses their TEXT column. * The former "STILL-OPEN half" cases below are the same measurements in their * CLOSED shape: the data-URI that was refused `22001` / `ER_DATA_TOO_LONG` at - * varchar(255) is accepted and round-trips byte-identically, and the #11374 + * varchar(255) is accepted and round-trips byte-identically, and commit d0e3a885b's * keyed-and-bounded rule applies to them the way it applies to every other * text-family member (keyed + bounded ⇒ varchar(maxLength), physically * enforced at exactly the declared bound; otherwise TEXT, bound enforced at @@ -205,7 +205,7 @@ describe('richtext joins the TEXT family (#11794) — physical shape on SQLite', // from a width. expect(mirror({ type: 'richtext' })).toBeNull(); expect(mirror({ type: 'code', maxLength: 64 })).toBeNull(); - // Keyed and bounded: varchar(maxLength) — the #11374 rule, so a declared + // Keyed and bounded: varchar(maxLength) — commit d0e3a885b's rule, so a declared // index on a bounded code field still keys on MySQL. expect(mirror({ type: 'code', maxLength: 64 }, { unique: true })).toBe(64); // Keyed and unbounded: still TEXT — MySQL then refuses the key BY NAME @@ -321,17 +321,17 @@ for (const liveCell of [PG_CELL, MYSQL_CELL]) { // seam (record-validator, pinned in objectql), keyed columns enforce // it physically too. Both directions measured, boundary included. const KT = `${T}_keyed`; - // Hoisted (not an inline literal) the way #11374's `boundedObject()` + // Hoisted (not an inline literal) the way commit d0e3a885b's `boundedObject()` // is, exactly as the platform objects declare it. // // ⚠️ The second half of what this comment used to say has EXPIRED and // is kept here as a dated record rather than deleted: it read // "`indexes` rides through `initObjects` beyond its narrow parameter // type", and that was true — the signature declared no `indexes` and - // the driver read the key through an `as any` anyway. #16570 declared - // it and #16711 closed the class, so the hoist is no longer LOAD-BEARING + // the driver read the key through an `as any` anyway. Commit b72226f48 declared + // it and commit 7862fb711 closed the class, so the hoist is no longer LOAD-BEARING // here; an inline literal would compile today. It stays because - // mirroring #11374's authoring shape is why it was written that way in + // mirroring commit d0e3a885b's authoring shape is why it was written that way in // the first place, and because this suite is about column widths, not // about parameter types. The pin that must stay inline is // `sql-driver-16711-object-def-param-keys.test.ts`. diff --git a/packages/drivers/driver-sql/src/sql-driver-12380-json-roundtrip.test.ts b/packages/drivers/driver-sql/src/sql-driver-12380-json-roundtrip.test.ts index 10b23661d5c..f6d3fac0794 100644 --- a/packages/drivers/driver-sql/src/sql-driver-12380-json-roundtrip.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-12380-json-roundtrip.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#12380] A `Field.json` column round-trips FAITHFULLY — what you wrote is what + * [commit 4045b954d] A `Field.json` column round-trips FAITHFULLY — what you wrote is what * you read back — on every dialect this driver speaks. * * ## What was measured, and why the contract decides it @@ -297,7 +297,7 @@ describe(`[#12380] driver-sql — Field.json round-trips faithfully (${cell.labe * * This block used to assert that the DDL was UNCHANGED — that a `Field.json` * column was still declared `json`, still carried NUMERIC affinity, and that - * #12380's encoded form survived it. #12738 changed the DDL: the SQLite family + * commit 4045b954d's encoded form survived it. #12738 changed the DDL: the SQLite family * now declares `text`, so NUMERIC affinity is gone from NEW columns and the * exposure is closed at the root rather than encoded around. * @@ -308,7 +308,7 @@ describe(`[#12380] driver-sql — Field.json round-trips faithfully (${cell.labe * so a bare number-like value written by raw SQL is no longer destroyed. * - **§B a LEGACY column** — declared `json` by hand, which is what every * database created before #12738 holds. NUMERIC affinity is still in force - * there and #12380's encoding still defeats it. This is the half the #12738 + * there and commit 4045b954d's encoding still defeats it. This is the half the #12738 * ruling requires to stay green: existing columns keep their declared type, * so the codec that protects them stays load-bearing forever. * @@ -354,7 +354,7 @@ describe('[#12738] SQLite affinity: gone from new columns, still defeated on leg async (raw) => { const bare = `bare_${raw}`; const enc = `enc_${raw}`; - // ONE statement, one column, two bindings: the pre-#12380 form and the + // ONE statement, one column, two bindings: the form from before commit 4045b954d and the // form `formatInput` produces. Bound through raw SQL so nothing but // SQLite's own affinity rule can be responsible for the outcome. await driver.execute( @@ -388,7 +388,7 @@ describe('[#12738] SQLite affinity: gone from new columns, still defeated on leg expect(rows[0].val).toBe(4200); }); - // ─── §B the legacy column — #12380 still in force, and still needed ─────── + // ─── §B the legacy column — commit 4045b954d's encoding still in force, and still needed ─────── it('[#12738] a LEGACY column is still declared `json` — the fixture is real', async () => { expect(await catalogType(driver, cell, LEGACY_T)).toBe('json'); @@ -406,7 +406,7 @@ describe('[#12738] SQLite affinity: gone from new columns, still defeated on leg const bareDisk = await diskCell(driver, cell, LEGACY_T, bare); const encDisk = await diskCell(driver, cell, LEGACY_T, enc); // Unchanged from the pre-#12738 assertion, on purpose: this is the exact - // measurement #12380 made, still true, now correctly scoped to the + // measurement commit 4045b954d made, still true, now correctly scoped to the // columns it is still true OF. expect(['integer', 'real'], `bare ${raw} must be eaten by NUMERIC affinity`).toContain(bareDisk.t); expect(encDisk.t, `encoded ${raw} must stay TEXT`).toBe('text'); diff --git a/packages/drivers/driver-sql/src/sql-driver-12998-shadow-null-safe-key.test.ts b/packages/drivers/driver-sql/src/sql-driver-12998-shadow-null-safe-key.test.ts index 8e322631add..e11c8c6e4b0 100644 --- a/packages/drivers/driver-sql/src/sql-driver-12998-shadow-null-safe-key.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-12998-shadow-null-safe-key.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #12998 — the hash shadow must carry the DECLARED key: NULL-safe organization + * Commit df1c75c4b — the hash shadow must carry the DECLARED key: NULL-safe organization * key parts (ADR-0120 D3) ride into the generation expression. * * ## The defect @@ -236,7 +236,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => { /** * The OVERFLOW TAIL — the half of that message no test in this repo could * see. The report is assembled by the module-local `formatDuplicateGroups` - * (#14902), shared with the drift entry and both plain-unique logs, and it + * (commit 61821e54c), shared with the drift entry and both plain-unique logs, and it * renders at most FIVE groups before counting the rest. Every duplicate * fixture in this package conflicts a single group, so the tail had never * been rendered by a test at all, and the `Conflicting group(s):` @@ -263,7 +263,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow NULL-safe key (#12998)', (cell) => { const bare = orgUniqueOn('os12998_tail'); // Bound to a variable, like the fixture above: `initObjects`' parameter // type does not declare `indexes`, and an inline literal would be - // rejected by tsc for a key the driver reads regardless (#16570). + // rejected by tsc for a key the driver reads regardless (the gap commit b72226f48 closed). const withoutIndex = { ...bare, indexes: [] }; await driver.initObjects([withoutIndex]); const knex = (driver as any).knex; diff --git a/packages/drivers/driver-sql/src/sql-driver-12999-stale-text-remedy.test.ts b/packages/drivers/driver-sql/src/sql-driver-12999-stale-text-remedy.test.ts index 7280baf352c..5bea023671d 100644 --- a/packages/drivers/driver-sql/src/sql-driver-12999-stale-text-remedy.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-12999-stale-text-remedy.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #12999 — the refusal message for an unkeyable TEXT column has TWO causes, and + * Commit ebcc34e89 — the refusal message for an unkeyable TEXT column has TWO causes, and * for one of them the advice it gave was a no-op. * * ## The defect @@ -9,7 +9,7 @@ * `explainUnkeyableTextColumn` rendered every `ER_BLOB_KEY_WITHOUT_LENGTH` / * `ER_TOO_LONG_KEY` index refusal as "the field declares no `maxLength` … * declare `maxLength` on the field(s)". True at CREATE time. False on the - * UPGRADE path, in both halves: once a release adds the bound (#12978 did + * UPGRADE path, in both halves: once a release adds the bound (commit e4902d2b9 did * exactly that for five `sys_notification_*` objects), the field DOES declare * one — but the additive sync never rewrites a column's type, so the physical * column stays TEXT, the index is refused again on every boot, and the message @@ -59,7 +59,7 @@ const beforeTheBound = () => ({ fields: { token: { type: 'text' } }, }); -/** The release that adds it — the #12978 shape, and the one that must not lie. */ +/** The release that adds it — commit e4902d2b9's shape, and the one that must not lie. */ const afterTheBound = () => ({ name: TABLE, fields: { token: { type: 'text', maxLength: 64 } }, diff --git a/packages/drivers/driver-sql/src/sql-driver-13015-shadow-carried-index-drift.test.ts b/packages/drivers/driver-sql/src/sql-driver-13015-shadow-carried-index-drift.test.ts index 5f2a26ef141..81d2b145c9f 100644 --- a/packages/drivers/driver-sql/src/sql-driver-13015-shadow-carried-index-drift.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-13015-shadow-carried-index-drift.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #13015 — a healthy #11627 hash-shadow UNIQUE is not drift, and the remedy the + * Commit cd1348802 — a healthy #11627 hash-shadow UNIQUE is not drift, and the remedy the * differ used to propose would have DROPPED the constraint it was reconciling. * * ## The defect @@ -44,8 +44,8 @@ import { describe, it, expect, afterEach } from 'vitest'; import { SqlDriver, diffManagedIndexes } from '../src/index.js'; // The shadow vocabulary stays INTERNAL to this package — nothing outside it -// consumes a hash shadow, so #13015 deliberately did not widen the published -// surface. Imported from the module, exactly as the #11627/#12998 suites do. +// consumes a hash shadow, so commit cd1348802 deliberately did not widen the published +// surface. Imported from the module, exactly as the #11627 and commit df1c75c4b suites do. import { enforcedIndexKey, hashShadowColumnFor, @@ -86,13 +86,13 @@ const carrier = (shadowKey?: PhysicalIndex['shadowKey']): PhysicalIndex => ({ ...(shadowKey ? { shadowKey } : {}), }); -/** What a HEALTHY (post-#12998) shadow hashes: the declared NULL-safe key. */ +/** What a HEALTHY (since commit df1c75c4b) shadow hashes: the declared NULL-safe key. */ const healthyKey = [ { column: 'organization_id', nullSafe: true }, { column: 'v', nullSafe: false }, ]; -/** What a PRE-#12998 shadow hashes: the same columns, RAW. */ +/** What a shadow from BEFORE commit df1c75c4b hashes: the same columns, RAW. */ const staleKey = [ { column: 'organization_id', nullSafe: false }, { column: 'v', nullSafe: false }, @@ -188,7 +188,7 @@ describe('shadow-carried UNIQUE is not index drift (#13015)', () => { it('resolves the enforced key from the stored generation expression', () => { // The spellings MySQL 8 stores, verbatim: single column, plain composite, - // and the NULL-safe composite #12998 introduced. + // and the NULL-safe composite commit df1c75c4b introduced. expect(parseHashShadowKeyParts('unhex(sha2(`v`,256))')).toEqual([ { column: 'v', nullSafe: false }, ]); @@ -350,7 +350,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) => /** * The direction a blind skip would have lost: a shadow hashing the RAW - * columns (what shipped before #12998) must still be reported AND must be + * columns (what shipped before commit df1c75c4b) must still be reported AND must be * repairable — the stale column is re-generated, not reused. */ it('reports and repairs a shadow that hashes the raw columns', async () => { @@ -361,7 +361,7 @@ declareDialectCell(MYSQL_CELL, 'shadow-carried index drift (#13015)', (cell) => const indexName = 'uniq_os13015_stale_org_v'; const shadow = hashShadowColumnFor(indexName); - // Reproduce the pre-#12998 physical state: raw CONCAT, no COALESCE. + // Reproduce the physical state from before commit df1c75c4b: raw CONCAT, no COALESCE. await knex.raw(`ALTER TABLE \`os13015_stale\` DROP INDEX \`${indexName}\``); await knex.raw(`ALTER TABLE \`os13015_stale\` DROP COLUMN \`${shadow}\``); await knex.raw( diff --git a/packages/drivers/driver-sql/src/sql-driver-13056-orphan-shadow-column-cleanup.test.ts b/packages/drivers/driver-sql/src/sql-driver-13056-orphan-shadow-column-cleanup.test.ts index 0c42eaa1cc6..538563981af 100644 --- a/packages/drivers/driver-sql/src/sql-driver-13056-orphan-shadow-column-cleanup.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-13056-orphan-shadow-column-cleanup.test.ts @@ -28,11 +28,11 @@ * - `drop_index` — TERMINAL. The declaration is gone; nothing will re-create * the name, so the shadow derived from it is dead. This is the leak. * - `recreate_index` — drops in order to re-create under the SAME name. Its - * shadow is deliberately kept: #13015's `reusable` branch re-keys the + * shadow is deliberately kept: commit cd1348802's `reusable` branch re-keys the * survivor in place instead of rebuilding the table around a regenerated * STORED column. A cleanup inside `dropIndexIfExists` would destroy exactly * that survivor on every rebuild. - * - `replace_unique_index` — cannot reach a shadow at all. #13015 already + * - `replace_unique_index` — cannot reach a shadow at all. Commit cd1348802 already * excludes `isHashShadowCarrier` from legacy detection, in `diffManagedIndexes`, * with a comment saying it does so *because* that op drops the legacy name. * A shadow-aware step there would be enforcement for a state the producer @@ -331,7 +331,7 @@ describe('the drop_index op collects the shadow it retires (#13056)', () => { }); /** - * #13015's `foreign` guard is the precedent, and this is the same refusal in + * Commit cd1348802's `foreign` guard is the precedent, and this is the same refusal in * the removal direction: a column of that name that is not generated may hold * user data and is not the driver's to drop. */ @@ -415,7 +415,7 @@ describe('the drop_index op collects the shadow it retires (#13056)', () => { /** * `recreate_index` drops and re-creates under the SAME name. Its shadow must - * SURVIVE, or #13015's `reusable` branch — which re-keys the survivor in + * SURVIVE, or commit cd1348802's `reusable` branch — which re-keys the survivor in * place rather than rebuilding the table around a regenerated STORED column — * can never be reached again. This is the assertion a cleanup moved into * `dropIndexIfExists` would fail. diff --git a/packages/drivers/driver-sql/src/sql-driver-13438-federated-missing-remote-envelope.test.ts b/packages/drivers/driver-sql/src/sql-driver-13438-federated-missing-remote-envelope.test.ts index 1b87f38cdfc..9e6034d59b0 100644 --- a/packages/drivers/driver-sql/src/sql-driver-13438-federated-missing-remote-envelope.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-13438-federated-missing-remote-envelope.test.ts @@ -4,7 +4,7 @@ * objectstack#13438 — the terminal backend-fault envelope DECLARES the table the * statement targeted, so a genuinely absent federated remote reads benign again. * - * ## The residual #13324 left behind + * ## The residual commit 4cda78c9b left behind * * `isMissingTableError(error, readObject)` refuses the benign "not provisioned * yet" verdict when the dialect phrase names a relation OTHER than the one the @@ -21,7 +21,7 @@ * * The driver declares the table it targeted on the envelope, and the predicate * prefers a declared name over the caller-supplied object name. The predicate's - * half — precedence, the dialect fixtures, the #13324 fence — is pinned in + * half — precedence, the dialect fixtures, commit 4cda78c9b's fence — is pinned in * `packages/types/src/driver-error-classification.targeted-table.test.ts`. This * suite pins the DRIVER's half, live, on every dialect it speaks: * @@ -181,11 +181,11 @@ for (const cell of DIALECT_CELLS) { } // ───────────────────────────────────────────────────────────────── -// SQLITE-ONLY — the #13324 fence, live, WITH the declaration present +// SQLITE-ONLY — commit 4cda78c9b's fence, live, WITH the declaration present // ───────────────────────────────────────────────────────────────── /** - * The defect #13324 closed, reproduced live: a VIEW whose base table is gone + * The defect commit 4cda78c9b closed, reproduced live: a VIEW whose base table is gone * raises `no such table: main.` — a phrase that answers the shape test * perfectly and names a relation the statement did NOT target. The envelope * now declares the view (what `getBuilder` targeted); the phrase names the diff --git a/packages/drivers/driver-sql/src/sql-driver-13973-canonical-iso-read-door.test.ts b/packages/drivers/driver-sql/src/sql-driver-13973-canonical-iso-read-door.test.ts index 3bda054b45f..c5a04ecfc95 100644 --- a/packages/drivers/driver-sql/src/sql-driver-13973-canonical-iso-read-door.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-13973-canonical-iso-read-door.test.ts @@ -18,7 +18,7 @@ * `Date` it is (pinned by `sql-driver-14078-invalid-date-materialisation.test.ts`; * never met here, because this fixture writes only valid instants). * `findWithWindowFunctions` used to be the one read door outside this list: it - * applied no read presentation of any kind. Since #16609 it routes each row + * applied no read presentation of any kind. Since commit 78bc4ad58 it routes each row * through the SAME `formatOutput` pass `find()` runs (minus the window-alias * columns), so it presents these two column classes exactly as the doors above * do — pinned by `sql-driver-window-function-output.test.ts`, whose live cells @@ -308,7 +308,7 @@ function measure(cell: DialectCell): void { for (const col of INSTANT_COLUMNS) expectCanonicalInstant(r[col], `bulkUpdate() return w${i} ${col}`); expect(r.closed_at, `bulkUpdate() return w${i} closed_at`).toBe(CLOSED_AT[i]); // A fresh stamp, in UTC — the same recency bound §A1 puts on `find()`. - // [#17690] `bulkUpdate()` publishes the contract's + // [commit be5c60291] `bulkUpdate()` publishes the contract's // `Record[]` now, so the stamp is typed before it is // parsed. const updatedAt = r.updated_at; @@ -347,7 +347,7 @@ function measure(cell: DialectCell): void { // the batch landed, its rows read back canonical through `find()`, and — // where the return carried a row — the return and the row agree value // for value, so the return door presents what the read door presents. - // [#17690] `find()` publishes `Record[]`, so every id + // [commit be5c60291] `find()` publishes `Record[]`, so every id // read off a returned row is narrowed before it is used as a key, and // `Array.prototype.find`'s absent arm is narrowed away rather than // asserted past. @@ -469,7 +469,7 @@ for (const cell of DIALECT_CELLS) { * not to `normalizeSqliteDatetimeOutput`. The two presenters differ on exactly * one input class, a NUMBER: the audit presenter passes it through (ADR-0074 * §3), the datetime fold turns it into ISO text. #13973's first cut routed the - * audit columns to the datetime fold, and the contract review of PR #16619 + * audit columns to the datetime fold, and the contract review recorded in commit 45cfa1b88 * reproduced the divergence that made: an author-declared `created_at: number` * read `1700000000000` off `find()` and `"2023-11-14T22:13:20.000Z"` off * `distinct()` and `max()`. Two reachable shapes carry a number there: diff --git a/packages/drivers/driver-sql/src/sql-driver-14902-plain-unique-duplicate-preflight.test.ts b/packages/drivers/driver-sql/src/sql-driver-14902-plain-unique-duplicate-preflight.test.ts index b042819a8bb..925f3451a03 100644 --- a/packages/drivers/driver-sql/src/sql-driver-14902-plain-unique-duplicate-preflight.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-14902-plain-unique-duplicate-preflight.test.ts @@ -4,7 +4,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { SqlDriver } from '../src/index.js'; /** - * #14902 — a PLAIN unique index over existing duplicate rows. + * Commit 61821e54c — a PLAIN unique index over existing duplicate rows. * * ## The defect, in the two shapes it was measured side by side * diff --git a/packages/drivers/driver-sql/src/sql-driver-15479-shadow-plain-unique-duplicates.test.ts b/packages/drivers/driver-sql/src/sql-driver-15479-shadow-plain-unique-duplicates.test.ts index bdf5363fb1f..80e5ddd499a 100644 --- a/packages/drivers/driver-sql/src/sql-driver-15479-shadow-plain-unique-duplicates.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-15479-shadow-plain-unique-duplicates.test.ts @@ -6,7 +6,7 @@ * * ## The defect * - * #14902 (PR #15477) brought the DIRECT arm to parity: a plain unique over + * Commit 61821e54c (PR #15477) brought the DIRECT arm to parity: a plain unique over * existing duplicates logs on the durability channel and lets the boot * continue, instead of throwing the database's raw error. The hash-shadow arm * — one branch above it in the SAME `catch`, taken when MySQL refuses to key @@ -53,7 +53,7 @@ const LONG = 'p'.repeat(900); * A tenancy-DISABLED object whose one long text field carries a PLAIN unique. * `maxLength: 1024` exceeds the keyable ceiling, so MySQL refuses the direct * index and the sync takes the shadow route; `tenancy: { enabled: false }` is - * one of the two shapes #14902 identified as reaching the plain path (the other + * one of the two shapes commit 61821e54c identified as reaching the plain path (the other * is an explicit `unique: 'global'`, exercised by `globalUniqueOn` below). */ const plainUniqueOn = (name: string) => ({ @@ -125,7 +125,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow plain unique over duplicates (#15479 ): Promise<{ logs: string[]; err: unknown }> => { driver = new SqlDriver(cell.config()); const logs = spy(); - // #16711: the `as any` that used to be on both of these calls was a + // Commit 7862fb711: the `as any` that used to be on both of these calls was a // workaround for `initObjects` not declaring `indexes`. The signature // declares it now, so the cast is gone and these two calls are checked // like any other. @@ -183,7 +183,7 @@ declareDialectCell(MYSQL_CELL, 'hash-shadow plain unique over duplicates (#15479 /** * The same disposition on the OTHER shape that reaches the plain path — an * explicit `unique: 'global'` on a tenanted object. Two shapes because - * #14902 measured both, and a guard keyed on the wrong one would pass here + * commit 61821e54c measured both, and a guard keyed on the wrong one would pass here * and fail in production. */ it("survives the boot under an explicit unique: 'global' on a tenanted object", async () => { diff --git a/packages/drivers/driver-sql/src/sql-driver-15683-temporal-text-operator-gate.test.ts b/packages/drivers/driver-sql/src/sql-driver-15683-temporal-text-operator-gate.test.ts index acccfdce1f7..fafabab764c 100644 --- a/packages/drivers/driver-sql/src/sql-driver-15683-temporal-text-operator-gate.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-15683-temporal-text-operator-gate.test.ts @@ -339,7 +339,7 @@ describe('[#15683] the per-dialect construct, compiled', () => { const d = new MultiProbeDriver(DIALECTS[0][1]).declareMulti(); const membership = d.compileWhere({ milestones: { $contains: '2026-01-05T00:00:00.000Z' } }); expect(membership).not.toMatch(/1 = 0/); - // [#17590] This row's own title said "it is membership, not a substring + // [commit e04a0aff2] This row's own title said "it is membership, not a substring // test" while the assertion under it named the SUBSTRING construct — the // only one that existed when it was written. It is a membership construct // now (`json_each` on this SQLite cell), so the assertion says what the diff --git a/packages/drivers/driver-sql/src/sql-driver-15989-file-column-move.test.ts b/packages/drivers/driver-sql/src/sql-driver-15989-file-column-move.test.ts index 78f8d7331c6..e668256dada 100644 --- a/packages/drivers/driver-sql/src/sql-driver-15989-file-column-move.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-15989-file-column-move.test.ts @@ -2,7 +2,7 @@ /** * [#15989] The ADR-0104 file-family COLUMN step, executed — per dialect, for - * BOTH encodings, across the window. The ruling on #15041 step 2, and the + * BOTH encodings, across the window. Step 2 of ADR-0104's 2026-09-05 addendum, and the * director ruling on this card (decision batch #120 item 1). * * `sql-driver-15989-file-family-bare-id.test.ts` pins what the two ARMS store @@ -13,7 +13,7 @@ * * ## §1 is the measurement this card exists for * - * The #15041 addendum prescribed `ALTER … USING (col #>> '{}')` with nothing in + * The ADR-0104 2026-09-05 addendum prescribed `ALTER … USING (col #>> '{}')` with nothing in * front of it, and required the step to abort *"on the first cell that is not a * JSON string"*. Those two sentences contradict each other, and which one was * wrong was settled by running it: `#>> '{}'` extracts ANY json type as text, so diff --git a/packages/drivers/driver-sql/src/sql-driver-15989-file-family-bare-id.test.ts b/packages/drivers/driver-sql/src/sql-driver-15989-file-family-bare-id.test.ts index 1f97411fc7b..fb4e9519e0b 100644 --- a/packages/drivers/driver-sql/src/sql-driver-15989-file-family-bare-id.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-15989-file-family-bare-id.test.ts @@ -4,7 +4,7 @@ * [#15989] The file family is stored as the BARE `sys_file` id in a string * column — per dialect, and for BOTH encodings across the ADR-0104 window. * - * Maintainer ruling on #15041, verbatim: 「15041 应该改为实际 id 保存。选A,其他 + * Maintainer ruling (ADR-0104's 2026-09-05 addendum), verbatim: 「15041 应该改为实际 id 保存。选A,其他 * 同意」. The physical column for `file` / `image` / `avatar` / `video` / * `audio` holds the actual id, not a JSON-quoted id in a JSON column. The * generator already emits `VARCHAR(2048)` for the family and does not move; the diff --git a/packages/drivers/driver-sql/src/sql-driver-16570-init-objects-indexes-param.test.ts b/packages/drivers/driver-sql/src/sql-driver-16570-init-objects-indexes-param.test.ts index e19b3c6dbb0..c624d9fd056 100644 --- a/packages/drivers/driver-sql/src/sql-driver-16570-init-objects-indexes-param.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-16570-init-objects-indexes-param.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#16570] `initObjects` and `registerObjectMetadata` accept `indexes` — the + * [commit b72226f48] `initObjects` and `registerObjectMetadata` accept `indexes` — the * key they have always READ — spelled as a **fresh object literal**. * * ## The defect this pins diff --git a/packages/drivers/driver-sql/src/sql-driver-16657-operator-facing-cause-text.test.ts b/packages/drivers/driver-sql/src/sql-driver-16657-operator-facing-cause-text.test.ts index 5c843f0d32c..31d10e9d843 100644 --- a/packages/drivers/driver-sql/src/sql-driver-16657-operator-facing-cause-text.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-16657-operator-facing-cause-text.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#16657] The producer↔consumer pin for `operatorFacingErrorText`. + * [commit 5a95b0e93] The producer↔consumer pin for `operatorFacingErrorText`. * * `@objectstack/types` cannot import a driver — every driver depends on it — * so the helper that reads the raw-path envelope carries its own copy of the diff --git a/packages/drivers/driver-sql/src/sql-driver-16711-object-def-param-keys.test.ts b/packages/drivers/driver-sql/src/sql-driver-16711-object-def-param-keys.test.ts index 1865e815f3e..9dce94669df 100644 --- a/packages/drivers/driver-sql/src/sql-driver-16711-object-def-param-keys.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-16711-object-def-param-keys.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#16711] The object-definition parameters on `SqlDriver` accept every key + * [commit 7862fb711] The object-definition parameters on `SqlDriver` accept every key * they READ, spelled as a **fresh object literal** — and still refuse a key * that is genuinely not one of them. * @@ -10,7 +10,7 @@ * `SqlDriver` reads keys off caller objects through `(obj as any).` while * the parameter's own inline literal declares none of them. Three instances * were carded and fixed one at a time before anyone called it a class: - * `tenancy` (#4311), `indexes` (#16570), and `lifecycle` here. Each fix left + * `tenancy` (#4311), `indexes` (commit b72226f48), and `lifecycle` here. Each fix left * the next one standing, and each looked complete from inside its own card. * * The escape is silent by construction. TypeScript's excess-property check @@ -105,7 +105,7 @@ describe('SqlDriver object-definition parameters accept the keys they read (#167 // The PUBLIC entry point of the rotation chain, with a fresh literal // carrying both keys the chain's leaf (`ensureShardTable`) reads. Before - // #16711 this call did not compile: `rotateShards` declared neither key, + // commit 7862fb711 this call did not compile: `rotateShards` declared neither key, // and the two casts that read them sat three links down. const state = await driver.rotateShards({ ...bareObject(T), @@ -140,7 +140,7 @@ describe('SqlDriver object-definition parameters accept the keys they read (#167 }); /** - * ⭐ THE NEGATIVE CONTROL (#16711 验收口径 item 4). + * ⭐ THE NEGATIVE CONTROL (验收口径 item 4 of the card commit 7862fb711 closed). * * Widening is only a fix while the accept set still has a boundary. A parameter * relaxed to `any`, or given an index signature, makes every assertion above @@ -172,7 +172,7 @@ export async function refusesKeysThatAreNotDeclared(driver: SqlDriver): Promise< } /** - * The narrowing axis, unchanged from #16570 and re-pinned here because the + * The narrowing axis, unchanged from commit b72226f48 and re-pinned here because the * `lifecycle` widening touches the same literal: a variable-bound argument * bypasses the excess-property check and is judged by ordinary assignability, * so the declared TYPES still bind. Compile-time only. diff --git a/packages/drivers/driver-sql/src/sql-driver-17343-multi-valued-boolean-membership.test.ts b/packages/drivers/driver-sql/src/sql-driver-17343-multi-valued-boolean-membership.test.ts index 29e575d8890..ad430b27659 100644 --- a/packages/drivers/driver-sql/src/sql-driver-17343-multi-valued-boolean-membership.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-17343-multi-valued-boolean-membership.test.ts @@ -1,13 +1,13 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#17343 · retargeted by #17469] The declared-type gate never fires on a JSON + * [commit 82cb69fed · retargeted by #17469] The declared-type gate never fires on a JSON * column — and the population of JSON columns is now the one the protocol * declares. * * ## What this file was filed for, and what happened to it * - * #17343: a `multiple: true` BOOLEAN column lost its `$contains` MEMBERSHIP + * The defect commit 82cb69fed fixed: a `multiple: true` BOOLEAN column lost its `$contains` MEMBERSHIP * filter — the carve-out #14079's declared-type gate never received on its * boolean limb, while its numeric limb carried one from the first line it * shipped and its temporal limb gained one in #15683. `{ FIELD: { $contains: @@ -51,7 +51,7 @@ * ## Which cells executed * * - **sqlite** — always, embedded. - * - **live mysql / live postgres** — run when provisioned. #17590's ruling + * - **live mysql / live postgres** — run when provisioned. The ruling commit e04a0aff2 records * (2026-09-12) replaced the text lowering with a real MEMBERSHIP construct * compiled per dialect, so all three answer the same rows and this file * carries no per-dialect branch. @@ -59,11 +59,11 @@ * @see SqlDriver.isNonTextColumn — the predicate; its JSON carve-out is the invariant. * @see SqlDriver.isJsonField — the storage half of the #17469 ruling. * @see https://github.com/objectstack-ai/objectstack/issues/17469 (the ruling that retargeted this file) - * @see https://github.com/objectstack-ai/objectstack/issues/17343 + * @see commit 82cb69fed * @see https://github.com/objectstack-ai/objectstack/issues/14079 (the gate) * @see https://github.com/objectstack-ai/objectstack/issues/15683 (the temporal carve-out) * @see https://github.com/objectstack-ai/objectstack/issues/7398 (the membership spelling it protects) - * @see https://github.com/objectstack-ai/objectstack/issues/17590 (the membership construct) + * @see commit e04a0aff2 (the membership construct) */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; @@ -251,11 +251,11 @@ describe('[#17343] the per-dialect construct, compiled — the registerExternalO const typed = (config: SqlDriverConfig) => new CompilerProbeDriver(config).declareMulti(); /** - * [#17590] "A real predicate over the column" per dialect — the pattern + * [commit e04a0aff2] "A real predicate over the column" per dialect — the pattern * emitter OR the membership construct that replaced it for `$contains`. This * file's question is whether the declared-type gate fired, so it must accept * either; asserting one SHAPE here would make it red on the card that changes - * the other, which is exactly what #17590 did to its predecessor. [#20024] + * the other, which is exactly what commit e04a0aff2 did to its predecessor. [#20024] * On SQLite the substring emitter spells `contains` as `instr(` and `ends` as * `substr(CAST(`; only `starts` and the `$like` pair keep `GLOB`. */ @@ -274,7 +274,7 @@ describe('[#17343] the per-dialect construct, compiled — the registerExternalO // JSON column now; the rest of the family is REFUSED there (`400`), // ahead of both this card's declared-type gate and the emitter. Either // way the gate this file is about does not fire: a refusal is not the - // `1 = 0` constant, and the SHAPE per operator is owned by #17590's + // `1 = 0` constant, and the SHAPE per operator is owned by commit e04a0aff2's // and #21009's own files. if (op !== '$contains') { let refusal: (Error & { code?: string; status?: number }) | undefined; @@ -289,7 +289,7 @@ describe('[#17343] the per-dialect construct, compiled — the registerExternalO } const sql = d.compileWhere({ [field]: { [op]: 'x' } } as FilterCondition); expect(sql, `${op} over ${field}`).not.toMatch(/1 = 0|1 = 1/); - // [#17590] `$contains` compiles the MEMBERSHIP construct. What this + // [commit e04a0aff2] `$contains` compiles the MEMBERSHIP construct. What this // card is about is not the shape — it is that the declared-type gate // does not fire — so this row asks for "a real predicate over the // column". diff --git a/packages/drivers/driver-sql/src/sql-driver-17586-multi-valued-boolean-read-inversion.test.ts b/packages/drivers/driver-sql/src/sql-driver-17586-multi-valued-boolean-read-inversion.test.ts index d465a254c72..c4e816c5b7c 100644 --- a/packages/drivers/driver-sql/src/sql-driver-17586-multi-valued-boolean-read-inversion.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-17586-multi-valued-boolean-read-inversion.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#17586 · retargeted by #17469] A JSON column's stored array survives the + * [commit d46deba19 · retargeted by #17469] A JSON column's stored array survives the * read — and `booleanFields` never contains one. * * ## What this file was filed for @@ -67,8 +67,8 @@ * @see SqlDriver.isNonTextColumn — the reader that carves out at the reader. * @see SqlDriver.isJsonField — the storage half of the #17469 ruling. * @see https://github.com/objectstack-ai/objectstack/issues/17469 (the ruling that retargeted this file) - * @see https://github.com/objectstack-ai/objectstack/issues/17586 - * @see https://github.com/objectstack-ai/objectstack/issues/17343 (the filter half) + * @see commit d46deba19 + * @see commit 82cb69fed (the filter half) * @see https://github.com/objectstack-ai/objectstack/issues/11782 (the pass) * @see https://github.com/objectstack-ai/objectstack/issues/11635 (the PG cast) */ @@ -98,7 +98,7 @@ const BYPASS: DriverOptions = { bypassTenantAudit: true }; * statement is refused before any row is presented (`could not identify an * equality operator for type json`). A property of the COLUMN CLASS, measured * on live PostgreSQL 16.13 across both legs of the original card's change and - * unchanged by it — the mirror of the `LIKE`-over-`json` divergence #17590 owns + * unchanged by it — the mirror of the `LIKE`-over-`json` divergence commit e04a0aff2 ruled * on the filter side, reached through the read door instead. */ const distinctExecutes = (cell: DialectCell): boolean => cell.id !== 'pg'; @@ -259,11 +259,11 @@ function declareReadSweep(cell: DialectCell): void { } else { /** * The NAMED DIVERGENCE, pinned rather than skipped — the same posture - * #17343's suite takes for the filter-side half of this property. + * commit 82cb69fed's suite takes for the filter-side half of this property. * * PostgreSQL's `json` type defines no equality operator and * `SELECT DISTINCT` needs one, so this door is REFUSED there for every - * JSON column. It is pinned as the ADR-0112 envelope #17639 brought to + * JSON column. It is pinned as the ADR-0112 envelope commit 7c2c5aedd brought to * this door, and on the CLASS rather than on a bare throw: `picks` is a * multi-valued `select` and `tags_` an inherently-multi option type, and * both must fail the SAME way, so a future edit that broke one of them @@ -287,7 +287,7 @@ function declareReadSweep(cell: DialectCell): void { expect(err, `distinct() over ${column} must be refused on this backend`).toBeDefined(); expect(err!.code, `code for ${column}`).toBe('DATABASE_ERROR'); expect(err!.status, `status for ${column}`).toBe(500); - // [#17639] The raw SQLSTATE the caller used to receive is the CAUSE now. + // [commit 7c2c5aedd] The raw SQLSTATE the caller used to receive is the CAUSE now. expect((err as unknown as { cause?: { code?: string } }).cause?.code, `SQLSTATE for ${column}`) .toBe('42883'); } @@ -426,7 +426,7 @@ describe('[#17586] the `booleanFields` registry and its four readers', () => { * The two registry fills, side by side. The omission the card repairs was * present in BOTH, and they are separate code with no shared helper to make * that impossible — so a repair reaching only one leaves the defect live on - * the other, exactly as #17343's round found. + * the other, exactly as commit 82cb69fed's round found. */ it('BOTH registry fills agree — initObjects and registerExternalObject register the same columns', async () => { const ext = external(DIALECTS[0][1]); diff --git a/packages/drivers/driver-sql/src/sql-driver-17590-json-column-membership.test.ts b/packages/drivers/driver-sql/src/sql-driver-17590-json-column-membership.test.ts index 17ad08ac88c..4c69cc0e6c2 100644 --- a/packages/drivers/driver-sql/src/sql-driver-17590-json-column-membership.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-17590-json-column-membership.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#17590, director ruling 2026-09-12] `$contains` on a multi-valued / JSON + * [commit e04a0aff2, director ruling 2026-09-12] `$contains` on a multi-valued / JSON * column is a MEMBERSHIP test, and `driver-sql` compiles it PER DIALECT so * SQLite, MySQL and PostgreSQL answer the SAME ROWS. * @@ -52,7 +52,7 @@ * - **live postgres** — the cell that carried the defect. Runs when * provisioned; measured here on PostgreSQL 16.13. * - **live mysql** — measured DIRECTLY, which is what the ruling asked for: - * the card's MySQL row was a second-hand reading off #17343's CI job. + * the card's MySQL row was a second-hand reading off commit 82cb69fed's CI job. * Measured here on MySQL 8.0.46. * * The three cells assert the SAME literal row sets, which is what "answer the @@ -61,9 +61,9 @@ * @see SqlDriver.applyJsonMembership — the emitter and its two fall-through cases. * @see jsonMembershipPredicate — the per-dialect construct and its measured table. * @see jsonMembershipCandidates — why one string comparand denotes two JSON scalars. - * @see https://github.com/objectstack-ai/objectstack/issues/17590 + * @see commit e04a0aff2 * @see https://github.com/objectstack-ai/objectstack/issues/7398 (the membership spelling) - * @see https://github.com/objectstack-ai/objectstack/issues/17343 (the boolean cell this covers) + * @see commit 82cb69fed (the boolean cell this covers) * @see https://github.com/objectstack-ai/objectstack/issues/17469 (the population predicate, unwidened) */ diff --git a/packages/drivers/driver-sql/src/sql-driver-17639-distinct-fault-envelope.test.ts b/packages/drivers/driver-sql/src/sql-driver-17639-distinct-fault-envelope.test.ts index 61ada54547b..936cb188710 100644 --- a/packages/drivers/driver-sql/src/sql-driver-17639-distinct-fault-envelope.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-17639-distinct-fault-envelope.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * objectstack#17639 — `distinct()` joins the enveloped read exits. + * Commit 7c2c5aedd — `distinct()` joins the enveloped read exits. * * ## The measurement this suite is built from * @@ -41,12 +41,12 @@ * ⛔ It is NOT a request to make `distinct()` ANSWER over a JSON column. The * call fails either way; what changes is whether the failure is CLASSIFIED. * Whether a `json` column should support a distinct read at all belongs with - * #17590, which owns the sibling `LIKE`-over-`json` divergence on the filter + * the card commit e04a0aff2 closed, which owned the sibling `LIKE`-over-`json` divergence on the filter * side of the same columns. This is the same split #11455 made on the * `aggregate()` door while #11152 / #11249 still owned the answer question: the * envelope is the half that holds whichever way that card rules. * - * ⚠️ RETIREMENT CLAUSE for the Postgres-only block at the bottom: if #17590 + * ⚠️ RETIREMENT CLAUSE for the Postgres-only block at the bottom: if a card after commit e04a0aff2 * rules that a `json` column should ANSWER a distinct read, those cases stop * failing and that block is RETIRED by that card — exactly as #11635 retired * #11455's boolean-aggregand block. What the all-dialect sweep pins is @@ -62,14 +62,14 @@ * would not run this statement* — which is the only claim the signal supports. * ⛔ Never `INVALID_QUERY` / 400: that would say *"asking for the distinct * values of this column is your mistake"*, a verdict about the request that - * #17590 has not made. + * commit e04a0aff2 has not made. * * | card | door | before | after | * |--------|-----------------|--------------------------------|----------------------| * | #8790 | `count()` WHERE | raw dialect error | `INVALID_FILTER`/400 | * | #8931 | read exits | raw dialect error, no `status` | `DATABASE_ERROR`/500 | * | #11455 | `aggregate()` | raw dialect error, no `status` | `DATABASE_ERROR`/500 | - * | #17639 | `distinct()` | raw dialect error, no `status` | `DATABASE_ERROR`/500 | + * | commit 7c2c5aedd | `distinct()` | raw dialect error, no `status` | `DATABASE_ERROR`/500 | * * ⭐ The envelope comes from the EXIT, not from recognising `42883` or the * words *equality operator* — the #8926 lesson (a predicate arm matched by @@ -86,7 +86,7 @@ * compiled from `filters`. A blanket arm would tell the author of * `distinct(o, 'nosuchcol')` — who passed no filter at all — that their FILTER * was wrong. #11541 closed that gap for `aggregate()` with a clause-attributing - * classifier; #17857 has since closed the `distinct()` half the same way + * classifier; commit 9ccc4179e has since closed the `distinct()` half the same way * (`SqlDriver.distinctBackendFault`, pinned by * `sql-driver-17857-distinct-unresolvable-column-refusal.test.ts`). What this * suite pins was unchanged by that, exactly as this note anticipated: an error @@ -177,7 +177,7 @@ describe(`[#17639] driver-sql — distinct() takes the backend-fault envelope ($ // A table that was never provisioned raises a dialect error on all three // backends (`42P01` / `SQLITE_ERROR` / `ER_NO_SUCH_TABLE`), so this is the // envelope invariant measured on EVERY cell — and it involves no JSON column, - // so #17590's ruling cannot move it in either direction. + // so the ruling commit e04a0aff2 records cannot move it in either direction. it('an unclassified dialect fault on the distinct door carries a code AND a status', async () => { const err = await caught(() => driver.distinct(MISSING_TABLE, 'title')); expect(err.code, 'code').toBe('DATABASE_ERROR'); @@ -202,8 +202,8 @@ describe(`[#17639] driver-sql — distinct() takes the backend-fault envelope ($ }); // ⛔ THE FENCE: the envelope claims nothing about the request. Listing the - // distinct values of a column is not a malformed query, and #17590 — not this - // exit — owns whether the column supports the read. + // distinct values of a column is not a malformed query, and the card commit e04a0aff2 closed — not this + // exit — owned whether the column supports the read. it('the envelope makes NO claim about the query or the filter', async () => { const err = await caught(() => driver.distinct(MISSING_TABLE, 'title')); expect(err.code).not.toBe('INVALID_QUERY'); @@ -299,7 +299,7 @@ for (const cell of DIALECT_CELLS) { // ───────────────────────────────────────────────────────────────── // // ⚠️ RETIREMENT CLAUSE: this block pins that the JSON-column refusal the card -// measured is ENVELOPED, never that it refuses. If #17590 rules that a `json` +// measured is ENVELOPED, never that it refuses. If a card after commit e04a0aff2 rules that a `json` // column should ANSWER a distinct read, these cases stop failing and this block // is RETIRED by that card — the same clause #11455's boolean-aggregand block // carried and #11635 fired. diff --git a/packages/drivers/driver-sql/src/sql-driver-17857-distinct-unresolvable-column-refusal.test.ts b/packages/drivers/driver-sql/src/sql-driver-17857-distinct-unresolvable-column-refusal.test.ts index 9c1e9910ee6..c6520d71a58 100644 --- a/packages/drivers/driver-sql/src/sql-driver-17857-distinct-unresolvable-column-refusal.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-17857-distinct-unresolvable-column-refusal.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * objectstack#17857 — the #8790 unresolvable-column refusal reaches the LAST + * Commit 9ccc4179e — the #8790 unresolvable-column refusal reaches the LAST * read door, attributed to the clause the caller's own request names. * * ## The five-row probe this card was filed from @@ -25,9 +25,9 @@ * naming nothing they could act on — and a picklist-populating `distinct()` * sits beside the `find()` and `count()` of the same list view. * - * ## What #17639 landed, and why it stopped where it did + * ## What commit 7c2c5aedd landed, and why it stopped where it did * - * #17639 gave this door the TERMINAL envelope (`DATABASE_ERROR` / 500 instead + * Commit 7c2c5aedd gave this door the TERMINAL envelope (`DATABASE_ERROR` / 500 instead * of pg's raw `DatabaseError`) and deliberately left the ATTRIBUTION arm filed, * with the reason written at the door: a BLANKET `isUnresolvableColumnError` * arm answers *"Filter on 'x' names a column …"*, and this door names columns @@ -48,7 +48,7 @@ * compiled from `filters` and the tenant-scope predicate, both filters, so * #8790's `unresolvableFilterColumnRefusal` applies verbatim; * 3. `unresolvableColumnNameOf` answers `null` ⇒ no attribution is supportable, - * so the #17639 terminal envelope stands unchanged. + * so commit 7c2c5aedd's terminal envelope stands unchanged. * * ⭐ Arm 2 is the COMPLEMENT of arm 1, never a search of the `filters` AST for * the name — pinned below on `{ $or: [{ nosuchcol: 1 }] }`. `FilterCondition` @@ -72,9 +72,9 @@ * * ## What this suite deliberately does NOT decide * - * ⛔ Nothing here touches #17590 (whether a `json` column should ANSWER a + * ⛔ Nothing here touches the card commit e04a0aff2 closed (whether a `json` column should ANSWER a * distinct read). That is a different condition — a column that EXISTS whose - * type has no equality operator — and it stays on #17639's terminal envelope, + * type has no equality operator — and it stays on commit 7c2c5aedd's terminal envelope, * whose own pins in `sql-driver-17639-distinct-fault-envelope.test.ts` are * unchanged by this card: an error this classifier does not claim still leaves * as `DATABASE_ERROR` / 500. @@ -144,7 +144,7 @@ async function withLog( /** * The disclosure clause, applied to one caller-visible message — the same - * NEGATIVE-set-plus-positive-anchor shape the #8931, #11455, #11541 and #17639 + * NEGATIVE-set-plus-positive-anchor shape the #8931, #11455, #11541 and commit 7c2c5aedd * suites use, so an emptied message cannot satisfy it trivially. */ function expectNoStatementShape(message: string, object: string, half: string): void { @@ -347,7 +347,7 @@ describe(`[#17857] driver-sql — distinct() attributes an unresolvable column ( ).toEqual(['Design']); }); - // ⛔ #17639's terminal is NOT narrowed by this card. A table that was never + // ⛔ Commit 7c2c5aedd's terminal is NOT narrowed by this card. A table that was never // provisioned is not an unresolvable COLUMN, so nothing here claims it. it('CONTROL an unclassified dialect fault still leaves as the #17639 terminal', async () => { const err = await caught(() => driver.distinct(MISSING_TABLE, 'title')); diff --git a/packages/drivers/driver-sql/src/sql-driver-20987-json-membership-move.test.ts b/packages/drivers/driver-sql/src/sql-driver-20987-json-membership-move.test.ts index 70a06c8bfec..f2228702776 100644 --- a/packages/drivers/driver-sql/src/sql-driver-20987-json-membership-move.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-20987-json-membership-move.test.ts @@ -5,7 +5,7 @@ * MEMBERSHIP emitter: the statement and its bindings, per dialect and per * comparand shape, are the ones this driver emitted before the predicate moved. * - * `jsonMembershipCandidates` and the per-dialect construct (#17590) were + * `jsonMembershipCandidates` and the per-dialect construct (commit e04a0aff2) were * module-private here. They moved to `@objectstack/core` * (`utils/json-membership-sql.ts`) so the analytics read scope and the * analytics `where` ask the same question this driver asks, from one @@ -23,7 +23,7 @@ * string `Number()` would accept but the JSON grammar refuses (`'0x10'`). * * `'unknown'` is a knex client this driver does not model (here `mssql`): it - * keeps the pre-#17590 `LIKE`, unchanged by the move. The scalar column beside + * keeps the `LIKE` from before commit e04a0aff2, unchanged by the move. The scalar column beside * the JSON one is the control: `$contains` stays the substring test there. */ diff --git a/packages/drivers/driver-sql/src/sql-driver-backend-fault-envelope.test.ts b/packages/drivers/driver-sql/src/sql-driver-backend-fault-envelope.test.ts index ce3681226cd..584b5c8d0cb 100644 --- a/packages/drivers/driver-sql/src/sql-driver-backend-fault-envelope.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-backend-fault-envelope.test.ts @@ -74,7 +74,7 @@ * the platform ACCEPTS and is expressly outside this ruling. * * The predicate already follows `error.cause` four levels deep, with its own - * pins (`packages/types/src/driver-error-classification.test.ts` — #13279 + * pins (`packages/types/src/driver-error-classification.test.ts` — commit 6a180e42d * moved it there from `metadata/src/utils/schema-sync-errors.test.ts` — * "follows an error wrapped as `cause`"), because "drivers commonly re-throw * with the original attached as `cause`" is a case it was built for. So the diff --git a/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts b/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts index fdb30016a7a..cfbaa906837 100644 --- a/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-datetime-mysql-storage.test.ts @@ -54,7 +54,7 @@ describe.skipIf(!URL)('Field.datetime on MySQL (#3942)', () => { let driver: SqlDriver; let serverTimeZone = ''; - // ── Why this beforeAll carries an explicit 60_000 budget (#14628) ── + // ── Why this beforeAll carries an explicit 60_000 budget (commit 6392b9c2b) ── // The live cell is one indirection away: this hook builds no driver of its // own, it calls `rawDriver()` above — which hard-codes `MYSQL_CELL.config()`, // unconditionally LIVE, not a parametrised `cell.config()` that would be diff --git a/packages/drivers/driver-sql/src/sql-driver-deferred-ddl-lock-wait.test.ts b/packages/drivers/driver-sql/src/sql-driver-deferred-ddl-lock-wait.test.ts index 90ac919493b..2b54722a52e 100644 --- a/packages/drivers/driver-sql/src/sql-driver-deferred-ddl-lock-wait.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-deferred-ddl-lock-wait.test.ts @@ -16,7 +16,7 @@ * whose code comes from the closed vocabulary and names the lock wait. No retry * logic, no configurability. * - * # #9542 — the same bound on boot, deliberately without the refusal + * # Commit 8bbf45947 — the same bound on boot, deliberately without the refusal * * The seam above separates "bound the wait" from "escape the swallow", and * #9354 armed only the flush, leaving boot schema-sync on the one-year default @@ -110,7 +110,7 @@ class FakeMysqlDriver extends SqlDriver { issued: Issued[] = []; /** - * [#9542/#9609] Every log line the driver emitted, **with its level**. + * [commit 8bbf45947, #9609] Every log line the driver emitted, **with its level**. * * On the boot path this is the ONLY output a blocked widening produces — the * swallow eats the error itself — so "the bound fires and the operator is @@ -378,7 +378,7 @@ describe('[#9354/#9542] a blocked widening ALTER — bounded on both paths, refu }); // ─────────────────────────────────────────────────────────────── - // BOOT (#9542) — the same bound, the opposite answer when it fires + // BOOT (commit 8bbf45947) — the same bound, the opposite answer when it fires // ─────────────────────────────────────────────────────────────── it('bounds BOOT sync too, and still swallows — boot is not the flush', async () => { @@ -390,7 +390,7 @@ describe('[#9354/#9542] a blocked widening ALTER — bounded on both paths, refu // but off the deferred path. This pin used to read the other way round: // boot ran the ALTER through the pool at MySQL's one-year default, so a boot // behind another session's metadata lock stopped at schema-sync, printed - // nothing, and could not be told from a crash. #9542 arms the bound here. + // nothing, and could not be told from a crash. Commit 8bbf45947 arms the bound here. await expect(driver.initObjects([WIDGET])).resolves.toBeUndefined(); const set = setStatements(driver); @@ -452,7 +452,7 @@ describe('[#9354/#9542] a blocked widening ALTER — bounded on both paths, refu // while something it claims is persisted has not landed? Here: yes. Boot // completed, traffic is served, and the `error` limb names this exact case // — "DDL that was supposed to run did not". The swallow is unchanged and - // deliberately so (#9542); only the level moved. + // deliberately so (commit 8bbf45947); only the level moved. const line = driver.logs.find((w) => /widen MySQL datetime columns/.test(w.msg)); expect(line?.level).toBe('error'); // ⭐ Asserted as an ABSENCE too, because `find` above would happily return @@ -529,7 +529,7 @@ describe('[#9354/#9542] a blocked widening ALTER — bounded on both paths, refu await expect(driver.initObjects([WIDGET])).resolves.toBeUndefined(); // ⚠️ This pin guards FLAG HYGIENE, not boot policy — it only ever shared an // assertion with the pin above. It used to read `setStatements → 0`, which - // since #9542 says nothing about the flag: a clean boot arms the bound too, + // since commit 8bbf45947 says nothing about the flag: a clean boot arms the bound too, // so that count is 2 either way. The observable that still discriminates is // the swallow on the line above (a stuck flag makes this same lock wait // escape `initObjects` as a refusal), and this line keeps it from passing diff --git a/packages/drivers/driver-sql/src/sql-driver-diagnostic-value-probe.test.ts b/packages/drivers/driver-sql/src/sql-driver-diagnostic-value-probe.test.ts index c675f091a7f..faae129c460 100644 --- a/packages/drivers/driver-sql/src/sql-driver-diagnostic-value-probe.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-diagnostic-value-probe.test.ts @@ -1,14 +1,14 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#9160] The instrument #8823 did not have: raise each candidate diagnostic + * [#9160] The instrument commit 4dfa369a9 did not have: raise each candidate diagnostic * family against a LIVE server and record what the server actually printed. * * ## Why this file exists * * `redactStatementFromMessage` (`@objectstack/objectql`) keeps the database's * diagnostic after the statement cut, on the premise that a diagnostic names - * IDENTIFIERS. #8823 found one family where that is false — MySQL's + * IDENTIFIERS. Commit 4dfa369a9 found one family where that is false — MySQL's * `ER_DUP_ENTRY` inlines the conflicting VALUE — and redacted that one slot. * * The list it introduced had exactly one entry and **no way to notice a second @@ -236,7 +236,7 @@ const PG_CASES: readonly ProbeCase[] = [ raise: (db) => db(PG_TABLE).insert({ age: 99999999999 }), }, { - // #8823's coincidence, re-measured. The value is on `detail`, which + // Commit 4dfa369a9's coincidence, re-measured. The value is on `detail`, which // `ObjectLogger.write` does not serialize — so Postgres is saved here by a // fact about our Logger, not by the cut. family: 'unique_violation (23505)', diff --git a/packages/drivers/driver-sql/src/sql-driver-distinct-filter-narrowing.test.ts b/packages/drivers/driver-sql/src/sql-driver-distinct-filter-narrowing.test.ts index 0ff64bc0f68..54850fa8a6b 100644 --- a/packages/drivers/driver-sql/src/sql-driver-distinct-filter-narrowing.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-distinct-filter-narrowing.test.ts @@ -5,7 +5,7 @@ * `FilterCondition`, never `any`. * * `distinct` is not declared on `IDataDriver`, so #5181's narrowing and - * #6075's follow-through never reached it; it kept `filters?: any` while its + * commit d367f03d6's follow-through never reached it; it kept `filters?: any` while its * body said something much more specific — `applyFilters(builder, filters)` * takes the argument ITSELF, so what it wants is the value `find()` carries * under `query.where`, not a query envelope. This file holds the type to that @@ -52,8 +52,8 @@ import { SqlDriver } from './index.js'; type IsAny = 0 extends 1 & T ? true : false; /** - * [#17879] MEASURED — this door's `IsAny` half is a PHANTOM half, and the - * `ContainsAny` detector (#17876) does NOT close it here. On disk, against + * [commit eb9334915] MEASURED — this door's `IsAny` half is a PHANTOM half, and the + * `ContainsAny` detector (commit be5c60291) does NOT close it here. On disk, against * this file's own driver, with both directions predicted before running: * * door resolves to `FilterCondition | undefined` @@ -67,7 +67,7 @@ type IsAny = 0 extends 1 & T ? true : false; * assertion forms; and `ContainsAny` is already `true` — * the contract type is an open map (`[key: string]: any`), so the detector is * SATURATED on the correct door and cannot separate it from a regression. - * No swap was made. The two measured repairs are in the #17879 report. + * No swap was made. The two measured repairs are in commit eb9334915's message. */ describe('SqlDriver.distinct takes a bare FilterCondition (#6320)', () => { diff --git a/packages/drivers/driver-sql/src/sql-driver-doors-declared-types.test.ts b/packages/drivers/driver-sql/src/sql-driver-doors-declared-types.test.ts index e4cfb4c0d9b..23a638c2749 100644 --- a/packages/drivers/driver-sql/src/sql-driver-doors-declared-types.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-doors-declared-types.test.ts @@ -3,7 +3,7 @@ // #15267 — the five remaining `IDataDriver` doors on `SqlDriver` publish their // declared return type, not `any`. // -// #14438 (PR #15280) un-masked `update()` on this class and filed the census of +// Commit 2200f8ec8 (PR #15280) un-masked `update()` on this class and filed the census of // what was left: `findOne`, `create`, `bulkCreate`, `execute` and `explain` // each carried an EXPLICIT `Promise` while // `packages/spec/src/contracts/data-driver.ts` had already declared every one @@ -39,7 +39,7 @@ // against the very `any` being removed. `findOne`'s `null` arm is the one door // that also has a runtime face, and it is exercised below. // -// The typed-const form is `sql-driver-update-declared-null.test.ts`'s (#14438), +// The typed-const form is `sql-driver-update-declared-null.test.ts`'s (commit 2200f8ec8), // which is `memory-update-declared-null.test.ts`'s (#13878). `TursoDriver` // overrides four of these five doors and carries its own copy of the driver // half in its own tsc program (`turso-driver-doors-declared-types.test.ts`); @@ -64,7 +64,7 @@ // not whether the door owes its declared type: optionality governs whether the // member EXISTS, not what it returns once it does. // -// #17690 adds four MORE doors of the same family — `find`, `upsert`, +// Commit be5c60291 adds four MORE doors of the same family — `find`, `upsert`, // `bulkUpdate` and `temporalFilterValue` — and the reason they were not in // #15267's repaired set nor in its deliberately-excluded set is worth one // paragraph, because it is the transferable half of this card. #15267's census @@ -106,7 +106,7 @@ type Equals = (() => T extends A ? 1 : 2) extends (() => T extends B type Resolved = F extends (...args: never[]) => PromiseLike ? R : never; /** - * [#17690] `IsAny` answers about T ITSELF, which is honestly `false` for + * [commit be5c60291] `IsAny` answers about T ITSELF, which is honestly `false` for * `any[]` and for `Record` — and those are exactly the two shapes * every door on this card had regressed to. Used as the "is not `any`" half of * a nested-`any` door it is a PHANTOM CHECK: it evaluates, it is green, and it @@ -131,7 +131,7 @@ type Resolved = F extends (...args: never[]) => PromiseLike ? R : ne * `Record[]` / `Record` / `unknown` answer * `false`. * - * [#17970] Answering `boolean` is the ONE failure mode this detector has to + * [commit 47e6601c5] Answering `boolean` is the ONE failure mode this detector has to * stay out of, and staying out of it takes TWO guards, because `T` can reach a * distributive conditional for two unrelated reasons. Every leg below is * spelled `const x: ContainsAny = false`, and `false` is ASSIGNABLE to @@ -176,7 +176,7 @@ type ContainsAnyPerMember = IsAny extends true : false; /** - * [#17970] The collapse. `ContainsAnyPerMember` is distributive, so on a + * [commit 47e6601c5] The collapse. `ContainsAnyPerMember` is distributive, so on a * union door it answers a UNION of per-member verdicts; this reports `false` * only when that union is exactly `false`, turning any `boolean` into `true`. */ @@ -192,7 +192,7 @@ type ContractExecute = Resolved; type ContractExplain = Resolved>; // `aggregate` is optional too (`aggregate?(...)`), read the same way (#17277). type ContractAggregate = Resolved>; -// [#17690] Four more doors. `temporalFilterValue` is synchronous, so it is read +// [commit be5c60291] Four more doors. `temporalFilterValue` is synchronous, so it is read // through `ReturnType` — `Resolved` would answer `never` and pin nothing. type ContractFind = Resolved; type ContractUpsert = Resolved; @@ -349,7 +349,7 @@ describe('SqlDriver declared return types on the five remaining IDataDriver door expect(Number(cell)).toBe(1); }); - // [#17690] The four doors a literal-string census could not see. Both halves + // [commit be5c60291] The four doors a literal-string census could not see. Both halves // each: put any one annotation back and `ContainsAny` flips to `true` while // `Equals` flips to `false`, reding this file twice for that door — verified // by ablating all four, two errors apiece and nothing else. diff --git a/packages/drivers/driver-sql/src/sql-driver-external-remote-name.test.ts b/packages/drivers/driver-sql/src/sql-driver-external-remote-name.test.ts index e8df02f704b..b96b3242dc1 100644 --- a/packages/drivers/driver-sql/src/sql-driver-external-remote-name.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-external-remote-name.test.ts @@ -90,7 +90,7 @@ describe('SqlDriver external read path — remoteName resolution (ADR-0015)', () expect(rows).toHaveLength(2); const acme = rows.find((r) => r.name === 'Acme'); - // [#17690] `find()` publishes `Record[]`, so + // [commit be5c60291] `find()` publishes `Record[]`, so // `Array.prototype.find` answers `… | undefined` and the absent arm is // narrowed away before any field is read. Through the old // `Promise` the four reads below compiled against nothing. diff --git a/packages/drivers/driver-sql/src/sql-driver-json-backfill-depth-limit.test.ts b/packages/drivers/driver-sql/src/sql-driver-json-backfill-depth-limit.test.ts index 5144fdd8ce0..9512c6fd5f7 100644 --- a/packages/drivers/driver-sql/src/sql-driver-json-backfill-depth-limit.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-json-backfill-depth-limit.test.ts @@ -2,7 +2,7 @@ /** * [#19912] The local `Field.json` storage backfill - * (`SqlDriver.backfillCanonicalJsonEncoding`, #12380) lets the driver's own + * (`SqlDriver.backfillCanonicalJsonEncoding`, commit 4045b954d) lets the driver's own * codec decide which cell to rewrite. SQL only pre-filters. * * The defect: the backfill was one `UPDATE … set col = json_quote(col) where @@ -92,7 +92,7 @@ afterEach(async () => { for (const dir of dirs.splice(0)) rmSync(dir, { recursive: true, force: true }); }); -/** A cell the way a pre-#12380 door (or any raw writer) left it: bound as-is. */ +/** A cell the way a door before commit 4045b954d (or any raw writer) left it: bound as-is. */ async function plantRaw(d: SqlDriver, id: string, val: unknown): Promise { await d.execute(`insert into "${T}" ("id", "label", "val") values (?, ?, ?)`, [id, id, val as any]); } @@ -116,7 +116,7 @@ describe('[#19912] the local json backfill leaves JSON nested past SQLite\'s dep it('the card\'s reproduction: only `bare` is quoted; the 1001-level array reads as an array after a SECOND backfill', async () => { const d = await makeDriver(); await d.syncSchema(T, SCHEMA); // creates the table: no backfill - await plantRaw(d, 'bare', 'bare'); // the pre-#12380 form of the string 'bare' + await plantRaw(d, 'bare', 'bare'); // the form of the string 'bare' before commit 4045b954d await d.create(T, { id: 'deep', label: 'deep', val: deepArray(1001) }, { bypassTenantAudit: true }); await d.create(T, { id: 'pair', label: 'pair', val: [1, 2] }, { bypassTenantAudit: true }); diff --git a/packages/drivers/driver-sql/src/sql-driver-json-column-operator-refusal.test.ts b/packages/drivers/driver-sql/src/sql-driver-json-column-operator-refusal.test.ts index 3e83f6d78dd..7fb0f054aea 100644 --- a/packages/drivers/driver-sql/src/sql-driver-json-column-operator-refusal.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-json-column-operator-refusal.test.ts @@ -170,7 +170,7 @@ const REFUSED: ReadonlyArray = [ * predicates, which ask about the column's presence — a well-formed question * whatever the column holds. * - * ⚠️ [#17590] The sentence that stood here said the `LIKE` family "matches the + * ⚠️ [commit e04a0aff2] The sentence that stood here said the `LIKE` family "matches the * serialization as text (which is how `$contains` works at all)". That was an * accurate description of a mechanism that has since been replaced: it made * `$contains` a SUBSTRING test over the serialization — right across element diff --git a/packages/drivers/driver-sql/src/sql-driver-keyed-text-mysql.test.ts b/packages/drivers/driver-sql/src/sql-driver-keyed-text-mysql.test.ts index d00cc3d52d0..df3f2e8c250 100644 --- a/packages/drivers/driver-sql/src/sql-driver-keyed-text-mysql.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-keyed-text-mysql.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * #11374 — a text-family field that a declared index KEYS ON. + * Commit d0e3a885b — a text-family field that a declared index KEYS ON. * * ## The defect this pins, and why nothing caught it * @@ -101,7 +101,7 @@ const tooWideObject = () => ({ * ⚠️ Why this file grew these: the two objects above declare UNIQUE indexes, and * #11627 made a UNIQUE index over an unkeyable column expressible — it is now * carried on a hash-shadow column instead of being refused. That is a ruled - * behaviour change (maintainer, 2026-08-24 on #11374), so the assertions that + * behaviour change (maintainer, 2026-08-24; landed as commit 107bb4ba4), so the assertions that * pinned "unkeyable ⇒ refused" for those objects were pinning a branch that no * longer exists for them, and were rewritten rather than deleted or silenced. * The refusal itself is NOT gone — it is the disposition for a NON-UNIQUE diff --git a/packages/drivers/driver-sql/src/sql-driver-query-signature.test.ts b/packages/drivers/driver-sql/src/sql-driver-query-signature.test.ts index b7c249aba12..715cb54babd 100644 --- a/packages/drivers/driver-sql/src/sql-driver-query-signature.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-query-signature.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * The driver side of #5181's `DriverQuery` narrowing (#6075). + * The driver side of #5181's `DriverQuery` narrowing (commit d367f03d6). * * `packages/spec/src/contracts/data-driver.test.ts` already pins the CONTRACT: * `IDataDriver`'s six query-taking methods declare `DriverQuery`. That pin says @@ -9,7 +9,7 @@ * compared bivariantly, so an implementation declaring the wider `QueryAST` * satisfies the narrower contract and every gate stays green. That is exactly * how five drivers kept a stale signature through a full `pnpm typecheck` - * (125/125) after #6076 merged. + * (125/125) after commit 6513c1749 landed. * * The cost of the gap was a dormant lie rather than a live defect: a caller is * now free to omit `object`, so an implementation declaring `query: QueryAST` @@ -83,7 +83,7 @@ describe('SqlDriver query signatures follow the DriverQuery contract (#6075)', ( }); /** - * The two SQL-driver-OWN query doors — not on `IDataDriver`, so #5181/#6075 + * The two SQL-driver-OWN query doors — not on `IDataDriver`, so #5181 and commit d367f03d6 * never reached them and both kept `query: any` (#6212). * * `any` on a query parameter is not "unchecked object name"; it is every check diff --git a/packages/drivers/driver-sql/src/sql-driver-shard-tenancy-opt-out.test.ts b/packages/drivers/driver-sql/src/sql-driver-shard-tenancy-opt-out.test.ts index bf86f77a3b5..1c19ff7658c 100644 --- a/packages/drivers/driver-sql/src/sql-driver-shard-tenancy-opt-out.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-shard-tenancy-opt-out.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#16729] The shard path resolves its tenant column through the STICKY + * [commit 0f38ab084] The shard path resolves its tenant column through the STICKY * opt-out record, so a rotation-declared platform-global object scopes its * declared `unique: 'organization'` index identically on the base table and on * every shard. diff --git a/packages/drivers/driver-sql/src/sql-driver-tenant-scope.test.ts b/packages/drivers/driver-sql/src/sql-driver-tenant-scope.test.ts index f16af708162..2dd289621e4 100644 --- a/packages/drivers/driver-sql/src/sql-driver-tenant-scope.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-tenant-scope.test.ts @@ -516,7 +516,7 @@ describe('SqlDriver tenant scope (organization_id)', () => { }); /** - * [#8778] `tenancy.organizationField` is STAMP-ONLY — the driver's tenant + * [commit 7901b2dd2] `tenancy.organizationField` is STAMP-ONLY — the driver's tenant * scoping must be blind to it. The key exists for the audit writer alone * (which column says who a row is ABOUT); the wall keeps answering a different * question (what the object is WALLED by) from `enabled` / `tenantField` / @@ -585,7 +585,7 @@ describe('tenancy.organizationField is read-neutral in the driver (#8778)', () = it('the unwalled credential-table shape stays unwalled: reads unscoped, inserts uninjected', async () => { // Pre-#8287-shaped row: no organization at all. Under any wall reading // `active_organization_id` or resurrecting a scope, this row vanishes for - // its own owner — the defect #8287 removed and #8778 must not reintroduce. + // its own owner — the defect #8287 removed and commit 7901b2dd2's stamp-only key must not reintroduce. await driver.create('api_key_like', { id: 'k0', name: 'legacy', revoked: false }); await driver.create('api_key_like', { id: 'k1', name: 'ci', active_organization_id: 'org_b', revoked: false }); diff --git a/packages/drivers/driver-sql/src/sql-driver-timestamps-without-ddl.test.ts b/packages/drivers/driver-sql/src/sql-driver-timestamps-without-ddl.test.ts index e73ce4ec85c..b0126fb81a7 100644 --- a/packages/drivers/driver-sql/src/sql-driver-timestamps-without-ddl.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-timestamps-without-ddl.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#11067] `updated_at` must advance on a deployment that never runs the + * [commit 479fba50d] `updated_at` must advance on a deployment that never runs the * driver's DDL — and must keep working on a hand-migrated table that genuinely * has no `updated_at` column. * diff --git a/packages/drivers/driver-sql/src/sql-driver-ttl-onlywhen-null-dialects.test.ts b/packages/drivers/driver-sql/src/sql-driver-ttl-onlywhen-null-dialects.test.ts index 67d934cf6b0..c8f6615ca0f 100644 --- a/packages/drivers/driver-sql/src/sql-driver-ttl-onlywhen-null-dialects.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-ttl-onlywhen-null-dialects.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#10165] Dialect-compile measurement for `{ $null: true }` inside a + * [commit 801296050] Dialect-compile measurement for `{ $null: true }` inside a * lifecycle `onlyWhen` reap scope — the confidence gap named on the card: * the prior round (#7826) covered schema parsing and a fake engine, but not * the REAL driver compile path. @@ -27,7 +27,7 @@ * `$null: false` must render `is not null`, and the TTL cutoff must * remain a bound comparison on the same statement. * - * 3. **[#10836] Live pg + mysql**: the same where EXECUTED against real + * 3. **[commit 7ab286e44] Live pg + mysql**: the same where EXECUTED against real * servers, through `PG_CELL` / `MYSQL_CELL`. Measurement 2 proves the SQL * *text*; it cannot prove the *server* returns those rows, and it never * exercises the ttl cutoff against the column type each dialect actually @@ -170,7 +170,7 @@ describe('ttl onlyWhen {$null} — real driver compile path, three dialects (#10 }); // ───────────────────────────────────────────────────────────────── -// [#10836] MEASUREMENT 3 — the same where, EXECUTED on live servers +// [commit 7ab286e44] MEASUREMENT 3 — the same where, EXECUTED on live servers // ───────────────────────────────────────────────────────────────── /** Table this file owns on the live servers. The SCHEMA it lands in is derived diff --git a/packages/drivers/driver-sql/src/sql-driver-unique-violation-predicate.test.ts b/packages/drivers/driver-sql/src/sql-driver-unique-violation-predicate.test.ts index 17768d3632b..2514a67a84b 100644 --- a/packages/drivers/driver-sql/src/sql-driver-unique-violation-predicate.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-unique-violation-predicate.test.ts @@ -6,7 +6,7 @@ * (the constraint is logged as not-enforced and reported by the ADR-0120 D4 * drift pre-flight) instead of taking the process down. * - * ⚠️ Since #14902 that branch has two arms, not one: the NULL-safe organization + * ⚠️ Since commit 61821e54c that branch has two arms, not one: the NULL-safe organization * composite AND the plain unique (`tenancy: { enabled: false }`, or an explicit * `unique: 'global'`), which used to fall through to `throw e`. The * discriminator below is what BOTH arms judge with, so its blind spots are now @@ -235,13 +235,13 @@ describe('syncDeclaredIndexes unique-violation discriminator (#6543)', () => { // ── The site's own business logic, untouched by the migration ───────────── /** - * ⚠️ RETIRED PIN, re-authored — #14902. + * ⚠️ RETIRED PIN, re-authored — commit 61821e54c. * * This block used to assert the opposite: 「leaves the `nullSafe.size > 0` * guard intact — a plain unique still fails the sync」, on the reasoning that * absorbing it 「would silently ship an unenforced constraint **the drift * pre-flight was never told about**」. That reasoning was right, and its - * premise is exactly what #14902 removed: the ADR-0120 D4 pre-flight now + * premise is exactly what commit 61821e54c removed: the ADR-0120 D4 pre-flight now * probes the plain unique too, so the drift pass IS told, and `os migrate * plan` reports the blocked op `destructive` with the offending rows instead * of calling it `safe`. @@ -301,7 +301,7 @@ describe('syncDeclaredIndexes unique-violation discriminator (#6543)', () => { // A non-unique index exists for an ACCESS PATH — it cannot raise a // uniqueness violation, so a failure that reads as one while creating it is - // something else entirely. #14902's `unique` limb is what keeps that + // something else entirely. Commit 61821e54c's `unique` limb is what keeps that // failing loudly instead of being logged away as an unenforced constraint // that was never declared in the first place. const rejected: any = await sync([NON_UNIQUE_INDEX]).then( diff --git a/packages/drivers/driver-sql/src/sql-driver-update-declared-null.test.ts b/packages/drivers/driver-sql/src/sql-driver-update-declared-null.test.ts index e0257a673dc..1bdf1b4727d 100644 --- a/packages/drivers/driver-sql/src/sql-driver-update-declared-null.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-update-declared-null.test.ts @@ -1,6 +1,6 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. // -// #14438 — `SqlDriver.update()`'s declared return type is the contract's, not +// Commit 2200f8ec8 — `SqlDriver.update()`'s declared return type is the contract's, not // `any`, and it carries the not-found arm. // // `SqlDriver.update()` has always answered a missing id with `null` @@ -8,7 +8,7 @@ // the rotation path's `return null` once every shard has been probed), while // its signature was written out as an EXPLICIT `Promise`. // `IDataDriver.update()` declares `Promise | null>` -// (the arm landed with #13878 / PR #14434 under the maintainer's 2026-09-01 +// (the arm landed with #13878 / commit 93940d492 under the maintainer's 2026-09-01 // ruling), and an explicit `any` satisfies that structurally — so `tsc` said // nothing, the published `.d.ts` of `@objectstack/driver-sql` read // `Promise`, and no caller holding a `SqlDriver` (or a `SqliteWasmDriver`, @@ -51,8 +51,8 @@ import { SqlDriver } from './index.js'; type IsAny = 0 extends 1 & T ? true : false; /** - * [#17879] MEASURED — `sqlUpdateIsAny` below is a PHANTOM half against a - * NESTED regression, and `ContainsAny` (#17876) does NOT close it. On disk, + * [commit eb9334915] MEASURED — `sqlUpdateIsAny` below is a PHANTOM half against a + * NESTED regression, and `ContainsAny` (commit be5c60291) does NOT close it. On disk, * reverting only this door in `sql-driver.ts`: * * door resolves to `Record | null` @@ -66,7 +66,7 @@ type IsAny = 0 extends 1 & T ? true : false; * `Record | null` answers `boolean` (`true` for the record arm, * `false` for `null`) — and `const leg: boolean = false` compiles. Every * door carrying the not-found arm has this shape. No swap was made; the two - * measured repairs are in the #17879 report. + * measured repairs are in commit eb9334915's message. */ /** Exact (mutual, non-`any`) type equality. */ type Equals = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false; diff --git a/packages/drivers/driver-sql/src/sql-driver-value-roundtrip-conformance.test.ts b/packages/drivers/driver-sql/src/sql-driver-value-roundtrip-conformance.test.ts index 5e01b23c74f..5833c3704d2 100644 --- a/packages/drivers/driver-sql/src/sql-driver-value-roundtrip-conformance.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-value-roundtrip-conformance.test.ts @@ -7,15 +7,15 @@ * * ## Why this file is matrix-routed and not SQLite-only * - * The defect that produced the table (#12380) was a *dialect* defect: SQLite's + * The defect that produced the table (fixed in commit 4045b954d) was a *dialect* defect: SQLite's * `Field.json` codec was not injective while Postgres and MySQL were faithful, * and the difference was invisible to a suite pinned to one client. So the * dialect axis is the whole point here, not a formality — this cell is the one * `MATRIXED` (#12136) exists to make real, and a SQLite-only version of this - * file would restate exactly the coverage that let #12380 survive. + * file would restate exactly the coverage that let the defect commit 4045b954d fixed survive. * * PG and MySQL are also the **regression control**: they were faithful before - * #12380's fix and must stay faithful after it. If a future change to the codec + * commit 4045b954d and must stay faithful after it. If a future change to the codec * moves the defect onto them instead of closing it, it goes red here first. * * ## Its relationship to `sql-driver-12380-json-roundtrip.test.ts` @@ -82,7 +82,7 @@ function declareRoundTrip(cell: DialectCell): void { } as DriverQuery)) as any[]; expect(rows).toHaveLength(1); const read = rows[0][c.column]; - // The type pin comes first: `'123'` read back as `123` is #12380's + // The type pin comes first: `'123'` read back as `123` is commit 4045b954d's // exact before-state, and it survives every value-only comparison. expect(typeof read, `typeof for ${c.name}`).toBe(typeof c.wrote); expect(read, `value for ${c.name}`).toStrictEqual(c.wrote); diff --git a/packages/drivers/driver-sql/src/sql-driver-window-function-output.test.ts b/packages/drivers/driver-sql/src/sql-driver-window-function-output.test.ts index e84553d1def..e1bc6cf88f9 100644 --- a/packages/drivers/driver-sql/src/sql-driver-window-function-output.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver-window-function-output.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * Rows leaving `findWithWindowFunctions()` (#16609). + * Rows leaving `findWithWindowFunctions()` (commit 78bc4ad58). * * It was the last read door that returned `await builder` with NO presentation: * no `formatOutput` (which every `find()` / `findOne()` row gets) and no @@ -188,15 +188,15 @@ describe('rows leaving findWithWindowFunctions() (#16609)', () => { expect(rows.map((r: any) => Number(r.rn))).toEqual([1, 2]); }); - // ── THE COLLISION RULING (#16609) ────────────────────────────────────── + // ── THE COLLISION RULING (commit 78bc4ad58) ────────────────────────────────────── // // An alias may be spelled the same as a declared field. SQL decides that // one before the driver sees it: `select *` plus ` as ok` projects // two columns named `ok`, and the row object keeps the LAST — so the // COMPUTED value wins the key and the declared column's value is not in the - // row at all. That was already true before #16609 and is unchanged by it. + // row at all. That was already true before commit 78bc4ad58 and is unchanged by it. // - // What #16609 rules is the second half: the winning value stays RAW. It is + // What commit 78bc4ad58 rules is the second half: the winning value stays RAW. It is // a computed number, so no declared field's presentation rule may touch it // — applying the `Field.boolean` rule here would fold ROW_NUMBER 1 and 2 // into `true` and `true` and destroy the value the caller asked for. diff --git a/packages/drivers/driver-sql/src/sql-driver.test.ts b/packages/drivers/driver-sql/src/sql-driver.test.ts index 9bb52f77aec..e6e1a75fd17 100644 --- a/packages/drivers/driver-sql/src/sql-driver.test.ts +++ b/packages/drivers/driver-sql/src/sql-driver.test.ts @@ -100,7 +100,7 @@ describe('SqlDriver (SQLite Integration)', () => { it('should update an object', async () => { const [bob] = await driver.find('users', { where: { name: 'Bob' } }); - // [#17690] `find()` publishes the contract's `Record[]` + // [commit be5c60291] `find()` publishes the contract's `Record[]` // now, so an id read off a row is narrowed before it is passed as one. assert( typeof bob.id === 'string' || typeof bob.id === 'number', diff --git a/packages/drivers/driver-sql/src/sql-driver.ts b/packages/drivers/driver-sql/src/sql-driver.ts index 64955b94308..cd55a4ca44f 100644 --- a/packages/drivers/driver-sql/src/sql-driver.ts +++ b/packages/drivers/driver-sql/src/sql-driver.ts @@ -333,7 +333,7 @@ const JSON_COLUMN_TYPES = new Set([ * * ⚠️ NOT a taste: it is the width `os generate migration --format sql` already * emits for the family (`VARCHAR(2048)` in `packages/cli/src/commands/ - * generate.ts`), and the maintainer ruling on #15041 is that the GENERATOR + * generate.ts`), and the maintainer ruling in ADR-0104's 2026-09-05 addendum is that the GENERATOR * states the ruled end-state and does not move — the driver is the side that * moves to meet it. A driver that created knex's default `varchar(255)` here * would open a fresh divergence between the two producers of the same column @@ -996,7 +996,7 @@ function unresolvableFilterColumnError(object: string, column: string | null): E * platform accepts — expressly outside this ruling. * * That predicate already follows `error.cause` up to four levels, with its own - * pins (`packages/types/src/driver-error-classification.test.ts` — #13279 + * pins (`packages/types/src/driver-error-classification.test.ts` — commit 6a180e42d * moved it there from `metadata/src/utils/schema-sync-errors.test.ts` — * "follows an error wrapped as `cause`"), because "drivers commonly re-throw * with the original attached as `cause`" is a case it was built for. So the @@ -1018,7 +1018,7 @@ function unresolvableFilterColumnError(object: string, column: string | null): E * object (ADR-0015) that is not the name in the statement: {@link * SqlDriver.getBuilder} targets `external.remoteName`. A genuinely absent * remote therefore raised a phrase naming `legacy_orders` against a caller - * naming `crm_order`, and the #13324 comparison read a real missing table as + * naming `crm_order`, and commit 4cda78c9b's comparison read a real missing table as * "about something else" — loud, for the one case the licence exists for. * Nothing at a call site can fold that away: the mapping lives on this * instance. @@ -1182,7 +1182,7 @@ function insertedRowsNotReadBackError(object: string, missingIds: unknown[], wri /** * [#9354] How long a widening ALTER waits for a metadata lock, in seconds. * - * Named for the seam it arrived on; since #9542 it governs BOTH callers of + * Named for the seam it arrived on; since commit 8bbf45947 it governs BOTH callers of * {@link SqlDriver.runWideningAlters} — the deferred-DDL flush and boot * schema-sync. * @@ -1217,7 +1217,7 @@ function insertedRowsNotReadBackError(object: string, missingIds: unknown[], wri * re-run once the blocker is gone — against an unbounded hang as the cost of * one that never fires. * - * # The same number on boot (#9542) + * # The same number on boot (commit 8bbf45947) * * Boot schema-sync arms this bound too, at the same value rather than a longer * one. Everything above is reasoning about how long a legitimate metadata-lock @@ -5239,7 +5239,7 @@ interface RowWidthContribution { * Render the duplicate groups a unique pre-flight probe found, for an operator * message: at most five groups, then a count of the rest. * - * Module-local on purpose (#14902). The two sites that report a blocked unique + * Module-local on purpose (commit 61821e54c). The two sites that report a blocked unique * — the drift entry and the boot-time durability log — must name the SAME rows * in the SAME shape, and a second hand-rolled `.slice(0, 5).join('; ')` is * exactly how the plain and the NULL-safe path drifted apart in the first @@ -5439,7 +5439,7 @@ export class SqlDriver implements IDataDriver { * registry: its readers present the stored form (SQLite INTEGER 0/1, MySQL * `tinyint(1)`) as one JS boolean. * - * ⚠️ [#17586] SCALAR only. A MULTI-VALUED boolean/toggle is deliberately + * ⚠️ [commit d46deba19] SCALAR only. A MULTI-VALUED boolean/toggle is deliberately * NOT here — the same carve-out {@link mediaFields} states just above, and * the one `numericFields` / `numericValueFields` carry in both fills. Its * value is a LIST of booleans in a JSON column, and "present this as ONE @@ -5469,7 +5469,7 @@ export class SqlDriver implements IDataDriver { * 3. `formatOutput`'s row pass — the [#11782] coercion this registry exists * for, and where the collapse was filed; * 4. {@link isNonTextColumn} — already carves multi-valued out AT THE READER - * (`&& !this.isJsonColumn(...)`, #17343), so its answer is UNCHANGED by + * (`&& !this.isJsonColumn(...)`, commit 82cb69fed), so its answer is UNCHANGED by * the narrowing rather than merely unharmed by it. */ protected booleanFields: Record = {}; @@ -5560,7 +5560,7 @@ export class SqlDriver implements IDataDriver { protected columnFieldByObject: Record> = {}; protected tablesWithTimestamps: Set = new Set(); /** - * [#11067] What is known about `updated_at` on a table this driver was told + * [commit 479fba50d] What is known about `updated_at` on a table this driver was told * about WITHOUT running DDL against it. * * ## Why {@link tablesWithTimestamps} could not answer this @@ -7114,7 +7114,7 @@ export class SqlDriver implements IDataDriver { // CRUD — IDataDriver core // =================================== - // [#17690] The return is the contract's own type. It was `Promise`, and the + // [commit be5c60291] The return is the contract's own type. It was `Promise`, and the // reason #15267's census never named this door is worth carrying: that census // matched the literal string `Promise`, and here the `any` is NESTED // inside a wider type, so the characters were not there to match. The door @@ -8298,7 +8298,7 @@ export class SqlDriver implements IDataDriver { * `updated_at` — as opposed to merely presuming it from the declared shape? * * The stronger of the two answers {@link stampsUpdatedAt} folds together, and - * the only one the INSERT door may act on. `presumed` (#11067) is deliberately + * the only one the INSERT door may act on. `presumed` (commit 479fba50d) is deliberately * excluded: that state exists so an UPDATE can speculate and then RECOVER * ({@link updateWithPresumedTimestamp}), and the upsert door has no such * recovery — a presumption that turned out wrong there would name a column @@ -8338,7 +8338,7 @@ export class SqlDriver implements IDataDriver { * ## Only an OBSERVED column is stamped * * {@link observedUpdatedAtColumn}, not {@link stampsUpdatedAt} — see there for - * why the #11067 presumption stops at the UPDATE door. + * why the commit 479fba50d presumption stops at the UPDATE door. */ protected stampUpsertUpdatedAt(object: string, formatted: Record): void { if (formatted.updated_at !== undefined && formatted.updated_at !== null) return; @@ -8411,7 +8411,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#11067] Should an UPDATE to `object` refresh `updated_at`? + * [commit 479fba50d] Should an UPDATE to `object` refresh `updated_at`? * * `true` on the DDL-observed tables exactly as before, and now also on a * table whose declared shape says it has the column — see @@ -8426,7 +8426,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#11067] Is that stamp still a PRESUMPTION — i.e. must this write carry the + * [commit 479fba50d] Is that stamp still a PRESUMPTION — i.e. must this write carry the * fallback? * * Only for a table in the `presumed` state and outside `tablesWithTimestamps`. @@ -8438,7 +8438,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#11067] Ask the DATABASE whether `object`'s physical table carries + * [commit 479fba50d] Ask the DATABASE whether `object`'s physical table carries * `updated_at`. `null` when the question could not be answered. * * ⛔ This is deliberately not a read of the failure's message. Every dialect @@ -8482,7 +8482,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#11067] Issue an UPDATE whose `updated_at` stamp is a PRESUMPTION, and + * [commit 479fba50d] Issue an UPDATE whose `updated_at` stamp is a PRESUMPTION, and * recover if the column turns out not to be there. * * ## Why this exists rather than option 1 on its own @@ -8583,7 +8583,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#14438] Declared as `IDataDriver.update()` declares it: the updated + * [commit 2200f8ec8] Declared as `IDataDriver.update()` declares it: the updated * record, or `null` when no row carries `id` — the un-rotated path answers * `formatOutput(...) || null` and the rotation path answers `null` once * every shard has been probed. The annotation used to be an explicit @@ -9259,7 +9259,7 @@ export class SqlDriver implements IDataDriver { throw refuseUpsertConflictOutsideWrittenOrganization(object, mergeKeys); } - // [#17690] The return is the contract's own type. It was `Promise>`, and the + // [commit be5c60291] The return is the contract's own type. It was `Promise>`, and the // reason #15267's census never named this door is worth carrying: that census // matched the literal string `Promise`, and here the `any` is NESTED // inside a wider type, so the characters were not there to match. The door @@ -9877,7 +9877,7 @@ export class SqlDriver implements IDataDriver { * usable — the rollback decision for the caller's OWN work stays the * caller's, which is the half of `upsert`'s reasoning that does transfer. */ - // [#17690] The return is the contract's own type. It was `Promise[]>`, and the + // [commit be5c60291] The return is the contract's own type. It was `Promise[]>`, and the // reason #15267's census never named this door is worth carrying: that census // matched the literal string `Promise`, and here the `any` is NESTED // inside a wider type, so the characters were not there to match. The door @@ -9926,7 +9926,7 @@ export class SqlDriver implements IDataDriver { * `updated_at` (list-view sorts, delta/incremental sync, cache invalidation, * audit), without erroring. * - * The decision is #11067's, unchanged and shared rather than re-derived: + * The decision is commit 479fba50d's, unchanged and shared rather than re-derived: * {@link stampsUpdatedAt} answers whether to stamp, {@link keepSuppliedUpdatedAt} * honours an opt-in historical import, and {@link updateWithPresumedTimestamp} * carries the speculative case so a hand-migrated table that genuinely lacks @@ -10027,7 +10027,7 @@ export class SqlDriver implements IDataDriver { options?: DriverOptions, ): Promise | null> { const formatted = this.applyWriteColumnMap(object, this.formatInput(object, data)); - // [#11067] One definition of the decision, shared with {@link update}. No + // [commit 479fba50d] One definition of the decision, shared with {@link update}. No // fallback is threaded here, and that is a property of the path rather than // an omission: `rotationShardsOf` returns shards only once `ensureRotation` // has run, and `initObjects` records the stronger `tablesWithTimestamps` @@ -10460,7 +10460,7 @@ export class SqlDriver implements IDataDriver { * `any` here was not "the object name goes unchecked", it was every check off * on the members this body READS: `where`'s filter dialect, `groupBy`'s node * union, `aggregations`' node shape. #5181 narrowed the six methods it swept - * and #6075 followed through on five drivers; this door was reached by + * and commit d367f03d6 followed through on five drivers; this door was reached by * neither. * * [#17277] The sentence that used to close the paragraph above — @@ -11035,7 +11035,7 @@ export class SqlDriver implements IDataDriver { } builder.distinct(field); - // [#17639] The THIRD read door joins the other two. `find()` and `count()` + // [commit 7c2c5aedd] The THIRD read door joins the other two. `find()` and `count()` // have carried the terminal envelope since #8931 and `aggregate()` since // #11455; this one still executed BARE, so any dialect refusal the // statement raised left the driver as the backend's own object — a raw @@ -11057,7 +11057,7 @@ export class SqlDriver implements IDataDriver { // values of this column — was logged as an UNHANDLED server fault. // // ⛔ NOT a decision about whether a JSON column should ANSWER a distinct - // read; that question is #17590's, on the same columns. Whatever this door + // read; that question belonged to the card commit e04a0aff2 closed, on the same columns. Whatever this door // ends up doing, it must not leak the backend's own object — so the // envelope is the half that lands here, exactly as #11455 landed it for // `aggregate()` while its own answer question was still open. @@ -11068,11 +11068,11 @@ export class SqlDriver implements IDataDriver { // `sql-driver-17639-distinct-fault-envelope.test.ts` asserts that on a // route (a table that was never provisioned) that has no JSON column in it. // - // ⛔ And still NO BLANKET `isUnresolvableColumnError` arm — #17857 closed - // the gap #17639 left FILED, and it closed it the way #11541 closed the + // ⛔ And still NO BLANKET `isUnresolvableColumnError` arm — commit 9ccc4179e closed + // the gap commit 7c2c5aedd left FILED, and it closed it the way #11541 closed the // `aggregate()` one: by ATTRIBUTING the column to a clause of the caller's // own request first. A blanket arm remains forbidden for the reason stated - // here since #17639 — it would tell the author of `distinct(o, 'nosuchcol')`, + // here since commit 7c2c5aedd — it would tell the author of `distinct(o, 'nosuchcol')`, // who passed no filter at all, that their FILTER was wrong — and // {@link SqlDriver.distinctBackendFault} is what makes that claim // unnecessary rather than what makes it safe. @@ -11101,7 +11101,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#17857] Which envelope a dialect error leaving {@link SqlDriver.distinct} + * [commit 9ccc4179e] Which envelope a dialect error leaving {@link SqlDriver.distinct} * deserves — the #8790 unresolvable-column refusal reaching the LAST read * door, without the attribution #8931 forbids. * @@ -11124,7 +11124,7 @@ export class SqlDriver implements IDataDriver { * distinct(t, 'nosuchcol') => DATABASE_ERROR 500 ← this card * ``` * - * A BLANKET `isUnresolvableColumnError` arm is still refused, and #17639 + * A BLANKET `isUnresolvableColumnError` arm is still refused, and commit 7c2c5aedd * wrote the reason at the door: this door names columns in TWO clauses — the * `field` being listed and the WHERE compiled from `filters` — so the WHERE * refusal's words ("Filter on 'x' names a column …") would tell the author of @@ -11148,7 +11148,7 @@ export class SqlDriver implements IDataDriver { * {@link SqlDriver.unresolvableFilterColumnRefusal} applies verbatim; * 3. {@link unresolvableColumnNameOf} answers `null` ⇒ the wording parsed by * nothing. With no name there is no request lookup, so NO attribution is - * supportable — the #17639 terminal envelope stands unchanged. ⛔ Reading + * supportable — commit 7c2c5aedd's terminal envelope stands unchanged. ⛔ Reading * `null` as license for the WHERE arm would attribute a clause on no * evidence, which is arm 2's own justification inverted. * @@ -11203,7 +11203,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#17857] Compose the refusal for the LISTED field of a distinct read whose + * [commit 9ccc4179e] Compose the refusal for the LISTED field of a distinct read whose * column the backend could not resolve, writing the dialect's own message to * the SERVER LOG on the way — the same statement-to-log, name-to-caller split * {@link SqlDriver.unresolvableFilterColumnRefusal} performs for the WHERE @@ -11244,7 +11244,7 @@ export class SqlDriver implements IDataDriver { */ protected unresolvableDistinctColumnRefusal(object: string, column: string, error: unknown): Error { const detail = (error as { message?: unknown } | null | undefined)?.message; - // The withholding rule is #7929's and this door's arm is #17857's — ids kept + // The withholding rule is #7929's and this door's arm is commit 9ccc4179e's — ids kept // in the comment, never in the emitted string: a log line reaches operators // and generated surfaces, where `#NNNN` resolves against nothing // (`pnpm check:doc-authoring`). @@ -11328,7 +11328,7 @@ export class SqlDriver implements IDataDriver { const rows = await builder; if (!Array.isArray(rows)) return rows; - // [#16609] The last read door that returned STORAGE forms. It handed back + // [commit 78bc4ad58] The last read door that returned STORAGE forms. It handed back // `await builder` with no presentation at all, while `find()`/`findOne()` // run every row through `formatOutput` and `aggregate()`/`distinct()` got // `presentReadValue` under #3797/#3849 — so one driver answered one @@ -11771,10 +11771,10 @@ export class SqlDriver implements IDataDriver { /** Create/column-sync one physical shard table (mirrors the managed-table * branch of {@link initObjects}, scoped to a shard). * - * #16711: `indexes` and `tenancy` are DECLARED here, on {@link ensureRotation} + * Commit 7862fb711: `indexes` and `tenancy` are DECLARED here, on {@link ensureRotation} * and on {@link rotateShards}, because this leaf reads both off the object the * public entry point was handed — a shard carries the base table's declared - * indexes (#11374) and must scope a `unique: 'organization'` index the same + * indexes (commit d0e3a885b) and must scope a `unique: 'organization'` index the same * way on every shard (ADR-0120 D1). Declaring them only here would leave the * two links above still narrowing the same value, so a caller spelling * `indexes` in a fresh literal to `rotateShards` would still be refused by a @@ -11797,7 +11797,7 @@ export class SqlDriver implements IDataDriver { // ahead of either. this.warnBuiltinColumnCollisions(shardName, obj.fields, builtinColumns, 'shard'); const exists = await this.knex.schema.hasTable(shardName); - // #11374: a shard carries the base table's declared indexes (below), so its + // Commit d0e3a885b: a shard carries the base table's declared indexes (below), so its // columns need the same keyable-text decision the managed path makes. const keyedColumns = indexedKeyColumns({ table: shardName, @@ -11842,7 +11842,7 @@ export class SqlDriver implements IDataDriver { // (ADR-0120 D1) must scope identically on every shard of the base table, // so the answer has to come from the base. // - // [#16729] Keyed by `baseTable`, and through the RECORDING resolver, not + // [commit 0f38ab084] Keyed by `baseTable`, and through the RECORDING resolver, not // the bare `computeTenantField`. The bare one reads this call's schema // alone, so a shard synced from a partial re-registration — one carrying // no `tenancy` block — fell through to the implicit `organization_id` @@ -12024,7 +12024,7 @@ export class SqlDriver implements IDataDriver { // Unconditional, on BOTH arms — see {@link mediaFields}. The read-side // legacy-encoding repair runs on a deployment that has not moved too. if (!isMultiValuedColumn(type, field) && FILE_REFERENCE_TYPES.has(type)) mediaCols.push(name); - // [#17586] SCALAR only — the house spelling its three neighbours in + // [commit d46deba19] SCALAR only — the house spelling its three neighbours in // this block already carry, and this line was the single omission. See // {@link booleanFields}: every reader of this registry presents its // entry as ONE JS boolean, which for a multi-valued (JSON) column @@ -12128,7 +12128,7 @@ export class SqlDriver implements IDataDriver { // `toggle` shares boolean storage/affinity, so it needs the same // read coercion (stored 1/0 → JS true/false) or it leaks back as a // number/string instead of a boolean (#field-zoo). - // [#17586] SCALAR only, like the three neighbours below: a + // [commit d46deba19] SCALAR only, like the three neighbours below: a // `multiple: true` boolean/toggle is a JSON column, and the read // coercion this registry exists for presents ONE JS boolean — which // collapses the parsed array to `true` whatever it holds. See @@ -12180,7 +12180,7 @@ export class SqlDriver implements IDataDriver { this.fractionalNumericFields[tableName] = fractionalCols; this.autoNumberFields[tableName] = autoNumberCols; this.tenantFieldByTable[tableName] = tenantField; - // [#11067] The declared shape's answer to "does this table carry + // [commit 479fba50d] The declared shape's answer to "does this table carry // `updated_at`?", installed here because here is the one place a managed // object reaches the driver on EVERY boot posture — `initObjects` calls // this first, and a `skipSchemaSync` boot calls it and stops. Presumed @@ -12233,7 +12233,7 @@ export class SqlDriver implements IDataDriver { * it affordable on exactly the cold-start-sensitive boots `skipSchemaSync` * exists to protect: it costs one pass over the object list, in memory. * - * It is the same ruling #7737/#10629 already made for FEDERATED objects — + * It is the same ruling #7737 already made for FEDERATED objects (commit 199ec4712) — * `OS_SKIP_SCHEMA_SYNC` is about DDL, and a binding that is DDL-free must * not ride on it — extended to the managed ones. * @@ -12265,7 +12265,7 @@ export class SqlDriver implements IDataDriver { // correctness. `src/sql-driver-16570-init-objects-indexes-param.test.ts` // pins the fresh-literal form so it cannot silently go back. // - // `lifecycle` was the third instance, and the one that made #16711 file the + // `lifecycle` was the third instance, and the one that made the card behind commit 7862fb711 file the // CLASS rather than a fourth single-key card: the loop below reads // `obj.lifecycle?.storage` to decide whether a table is time-sharded, while // the sibling `rotateShards` on this same class had always declared the key. @@ -12372,7 +12372,7 @@ export class SqlDriver implements IDataDriver { // rejects CREATE TABLE with two columns of the same name). const builtinColumns = new Set(['id', 'created_at', 'updated_at']); - // #11374: which columns this object's indexes will KEY ON, resolved before + // Commit d0e3a885b: which columns this object's indexes will KEY ON, resolved before // any DDL runs. `createColumn` needs it to decide whether a bounded text // field takes `varchar(maxLength)` (keyable) or TEXT — a decision that is // only makeable at CREATE time, since no dialect turns a TEXT column into @@ -12488,7 +12488,7 @@ export class SqlDriver implements IDataDriver { await this.backfillCanonicalDatetimes(tableName, exists); // #3994: the `Field.time` twin of the line above. await this.backfillCanonicalTimes(tableName, exists); - // #12380: converge this table's `Field.json` columns on the injective + // Commit 4045b954d: converge this table's `Field.json` columns on the injective // JSON-text storage form the rewritten `formatInput` now writes. await this.backfillCanonicalJsonEncoding(tableName, exists); // #3942: the MySQL twin — widen legacy `TIMESTAMP` columns to `DATETIME(3)`. @@ -12670,7 +12670,7 @@ export class SqlDriver implements IDataDriver { /** * Converge one table's `Field.json` columns on the injective JSON-text - * storage form (#12380) — the `Field.json` twin of + * storage form (commit 4045b954d) — the `Field.json` twin of * {@link backfillCanonicalDatetimes}, built the same way for the same reasons. * * SQLite only. Postgres and MySQL never had the defect: their half of @@ -13031,7 +13031,7 @@ export class SqlDriver implements IDataDriver { * the lock behaviour of unrelated runtime work. The restore is best-effort: * it must never mask the refusal it runs alongside. * - * # Armed on BOTH callers; only the flush escapes the swallow (#9542) + * # Armed on BOTH callers; only the flush escapes the swallow (commit 8bbf45947) * * The bound is armed unconditionally, because the year-long default is no * better for boot than it is for an operator: a boot blocked on another @@ -13074,7 +13074,7 @@ export class SqlDriver implements IDataDriver { try { await run(s.sql, s.bindings); } catch (err) { - // #9542: the bound is armed on both callers, the ESCAPE is not. + // Commit 8bbf45947: the bound is armed on both callers, the ESCAPE is not. // Off the flush this rethrows the server's own error, which the // widening's catch reports and swallows — boot's policy // unchanged, now reached by a wait that ends. @@ -13216,7 +13216,7 @@ export class SqlDriver implements IDataDriver { * * # The level is `error`, and that is a separate question from the swallow (#9609) * - * Swallow-vs-throw was adjudicated (#9542) and is unchanged: boot must not go + * Swallow-vs-throw was adjudicated (commit 8bbf45947) and is unchanged: boot must not go * down over a migration. `warn`-vs-`error` was never separately decided, and * AGENTS.md → "Degradation log levels" decides it with one question — after * the degradation, does the system still look normal from the outside while @@ -13572,7 +13572,7 @@ export class SqlDriver implements IDataDriver { // #12732: `diffManagedTable`'s varchar-length branch asks `createColumn`'s // own read-only mirror (`varcharColumnChars`) whether it would even build // a varchar for a given field — and for the text family that answer needs - // keyedness (#11374), the same input `initObjects` / `ensureShardTable` + // keyedness (commit d0e3a885b), the same input `initObjects` / `ensureShardTable` // already resolve via `indexedKeyColumns` before any DDL. Resolved here // too so the DIFFER'S expectation, not only the DDL, agrees with keyed // columns. @@ -13658,7 +13658,7 @@ export class SqlDriver implements IDataDriver { * `safe` to blocked with the same row report — the CREATE could only * fail at apply time otherwise, with a raw driver error naming no rows. * - * ⚠️ #14902 — the second bullet covers the PLAIN unique too: an index with no + * ⚠️ Commit 61821e54c — the second bullet covers the PLAIN unique too: an index with no * organization key part at all, reached by an object with * `tenancy: { enabled: false }` or by any explicit `unique: 'global'`. The * `nullSafeColumns.length > 0` guard used to exclude it, so `os migrate plan` @@ -13691,7 +13691,7 @@ export class SqlDriver implements IDataDriver { // keeps its pre-ADR-0120 semantics untouched. if (op.type === 'recreate_index' && !tighten) continue; // …and a PLAIN unique has no tightening shape at all, so only its CREATE - // reaches the probe (#14902). + // reaches the probe (commit 61821e54c). if (!nullSafeKey && op.type !== 'create_index') continue; let duplicates: Array<{ key: string; rows: number }>; @@ -13730,7 +13730,7 @@ export class SqlDriver implements IDataDriver { `UNIQUE is NULL-distinct, so it never constrained rows without an organization): ` + `${report}. The op is BLOCKED: apply re-probes and refuses, and the existing index stays in place ` + `(ADR-0120 D4). Deduplicate the listed rows, then re-run "os migrate plan".` - : // #14902: the plain unique has no #5030 history behind it — nothing + : // Commit 61821e54c: the plain unique has no #5030 history behind it — nothing // ever admitted these rows, the constraint is simply newly declared // over data that does not satisfy it. So the message says what IS // true, and above all withdraws the `safe` claim: this op is not @@ -14129,7 +14129,7 @@ export class SqlDriver implements IDataDriver { // ⚠️ Deliberately HERE and not inside `dropIndexIfExists`. That helper // has two other callers and neither is terminal: `recreate_index` // drops in order to re-create under the SAME name — routing it through - // this cleanup would destroy the survivor #13015's `reusable` branch + // this cleanup would destroy the survivor commit cd1348802's `reusable` branch // exists to re-key in place, turning every rebuild into a full // regeneration of a STORED generated column — and // `replace_unique_index` cannot reach a shadow at all (its legacy @@ -14615,14 +14615,14 @@ export class SqlDriver implements IDataDriver { /** * Record, on each #11627 hash-shadow CARRIER, the declared key its shadow - * actually hashes (#13015). + * actually hashes (commit cd1348802). * * ## Why introspection and not the differ * * A carrier is recognisable by name alone — its sole key column is * {@link SqlDriver.hashShadowColumnFor} of its own index name — but a NAME * cannot say WHAT is hashed, and that difference decides between two - * opposite verdicts. A shadow written since #12998 hashes the declared key + * opposite verdicts. A shadow written since commit df1c75c4b hashes the declared key * with its NULL-safe `COALESCE(organization_id, '__global__')` parts intact * and is HEALTHY; one written before it hashes the RAW columns, so `CONCAT` * yields NULL for every NULL-organization row and the constraint those rows @@ -14818,7 +14818,7 @@ export class SqlDriver implements IDataDriver { * at `error` (a declared constraint is not enforced — the * durability-degradation rule) and surfaces as drift with a row report via * the ADR-0120 D4 pre-flight, instead of failing the whole boot. - * - #14902: a PLAIN unique — no organization key part, i.e. + * - Commit 61821e54c: a PLAIN unique — no organization key part, i.e. * `tenancy: { enabled: false }` or an explicit `unique: 'global'` — over * data that already violates it gets the SAME disposition, where it used to * throw the database's raw error and take the boot down naming no rows and @@ -14905,7 +14905,7 @@ export class SqlDriver implements IDataDriver { // `code` / `errno` / `message` / `cause`; see // `@objectstack/types`' `unique-violation.ts` for why it is the one // name for this question. - // #11374: MySQL's refusal of a TEXT key part names a column in a table + // Commit d0e3a885b: MySQL's refusal of a TEXT key part names a column in a table // that was just created successfully, which reads as an index quirk // rather than what it is — the object is now registered with its // declared uniqueness absent. Re-throw the SAME failure carrying the @@ -14933,7 +14933,7 @@ export class SqlDriver implements IDataDriver { // nothing. Those cases stay refused below, and stay tracked. if (unique) { try { - // #12998: the shadow must hash the DECLARED key, so the NULL-safe + // Commit df1c75c4b: the shadow must hash the DECLARED key, so the NULL-safe // organization key parts (ADR-0120 D3) ride along — without them // the generation expression hashed the RAW columns, `CONCAT` // returned NULL for every NULL-organization row, and the rows the @@ -14951,7 +14951,7 @@ export class SqlDriver implements IDataDriver { continue; } if (nullSafe.size > 0 && isUniqueViolationError(shadowErr)) { - // #12998: the shadow ALTER computes the generated column for the + // Commit df1c75c4b: the shadow ALTER computes the generated column for the // EXISTING rows, so a database that accumulated duplicates under // the NULL-safe key while the constraint was void fails here // with a uniqueness violation — the same data-dependent @@ -14999,7 +14999,7 @@ export class SqlDriver implements IDataDriver { // DIED carrying `ER_BLOB_KEY_WITHOUT_LENGTH` -- a message about // an unkeyable TEXT column, telling the operator to declare a // `maxLength` the field already declares, naming NO rows and NO - // remedy -- while the actual cause was duplicate rows. #14902 + // remedy -- while the actual cause was duplicate rows. Commit 61821e54c // fixed exactly that on the direct arm; the two arms of one // `catch` then disagreed about one question. // @@ -15064,7 +15064,7 @@ export class SqlDriver implements IDataDriver { continue; } if (unique && isUniqueViolationError(e)) { - // #14902 — the PLAIN unique: no organization key part at all, reached + // Commit 61821e54c — the PLAIN unique: no organization key part at all, reached // by `tenancy: { enabled: false }` or by an explicit // `unique: 'global'`. It used to fall through to `throw e`, so the // boot DIED carrying the database's own error, which names the index @@ -15779,7 +15779,7 @@ export class SqlDriver implements IDataDriver { * author declared non-temporal (`applySystemFields` lets the declaration * win; `AUDIT_FIELD_GOVERNANCE` forces only `readonly` / `system`, never * `type`) leaves `find()` as the number it is — routed to the datetime fold, - * both became ISO text at this door and nowhere else (the #16619 contract + * both became ISO text at this door and nowhere else (commit 45cfa1b88's contract * review's finding; `sql-driver-13973-canonical-iso-read-door.test.ts` §D * pins the agreement). * @@ -15842,7 +15842,7 @@ export class SqlDriver implements IDataDriver { * (`16`, `5`, `15`, `Infinity`) and this door as the string; that is * reachable through `create()` / `update()` on the driver's own DDL with an * author-declared non-temporal audit column, not only through a hand-made - * TEXT-affinity column (measured in the #16619 contract review). A decimal + * TEXT-affinity column (measured in the contract review commit 45cfa1b88 records). A decimal * or exponent spelling (`'1700000000000'`, `'1e3'`, `'.5'`) is folded to * INTEGER/REAL by the affinity before it is read back, and a number passes * both presenters untouched, so those agree. The B1 ruling did not decide @@ -16079,7 +16079,7 @@ export class SqlDriver implements IDataDriver { * caller flips its operator, which is exactly the ambiguity an * operator-sensitive rule avoids. */ - // [#17690] The contract declares this hook `unknown`-returning; the class + // [commit be5c60291] The contract declares this hook `unknown`-returning; the class // published a bare `any`, which is the same family as the promise-shaped // doors above and the one member of it that is synchronous. Pinned through // `ReturnType` rather than `Resolved` in @@ -16164,7 +16164,7 @@ export class SqlDriver implements IDataDriver { } /** - * [#14079/#15683/#17343] Is `localField` a column on `table` a text operator + * [#14079/#15683, commit 82cb69fed] Is `localField` a column on `table` a text operator * must not be aimed at — a SCALAR column DECLARED numeric, boolean or * temporal? * @@ -16222,13 +16222,13 @@ export class SqlDriver implements IDataDriver { * - **temporal** [#15683] — HERE. `dateFields` / `datetimeFields` / * `timeFields` serve the read-presentation seam, which DOES apply to a * multi-valued column, so narrowing them would break a seam that is right. - * - **boolean** [#17343] — HERE, and this limb had NEITHER until then. + * - **boolean** [commit 82cb69fed] — HERE, and this limb had NEITHER until then. * #14079 landed this predicate describing itself as "a declared numeric or * boolean SCALAR" and annotated the numeric registry as non-`multiple`, so * the omission was the gap between that stated scope and `booleanFields`' * silence. * - * ⚠️ [#17586] `booleanFields` was SINCE narrowed at both fills, for a + * ⚠️ [commit d46deba19] `booleanFields` was SINCE narrowed at both fills, for a * defect of its own (the read coercion collapsed a parsed array to a * single, inverted `true`). * @@ -16689,11 +16689,11 @@ export class SqlDriver implements IDataDriver { } /** - * [#17590, director ruling 2026-09-12] Emit the MEMBERSHIP reading of + * [commit e04a0aff2, director ruling 2026-09-12] Emit the MEMBERSHIP reading of * `$contains` / `$notContains` when the column they were aimed at is a JSON * column, and say whether it did. * - * Returns `false` — leaving the caller on the pre-#17590 substring emitter — + * Returns `false` — leaving the caller on the substring emitter from before commit e04a0aff2 — * in exactly two cases, and the two are different in kind: * * 1. **The column is not a JSON column.** On a scalar string column @@ -17175,7 +17175,7 @@ export class SqlDriver implements IDataDriver { ); break; } - // [#17590] The MEMBERSHIP reading first: on a JSON column this + // [commit e04a0aff2] The MEMBERSHIP reading first: on a JSON column this // operator asks whether the comparand is an ELEMENT of the stored // array, not whether it is a substring of the serialization. Falls // through to the substring emitter for every scalar string column, @@ -17195,7 +17195,7 @@ export class SqlDriver implements IDataDriver { this.applyLike(builder, method, field, opValue, 'contains', false, true); break; case '$notContains': - // [#17590] The exact complement of the arm above, on the same + // [commit e04a0aff2] The exact complement of the arm above, on the same // population and the same construct. It moves WITH `$contains` // and cannot be deferred: this operator is declared "the negation // of $contains, on the same comparand contract", so leaving it on @@ -18038,7 +18038,7 @@ export class SqlDriver implements IDataDriver { /** * The widest `varchar(n)` one utf8mb4 key part can hold on InnoDB: 3072 bytes - * of index key ÷ 4 bytes per character (#11374). + * of index key ÷ 4 bytes per character (commit d0e3a885b). * * Measured on MySQL 8.0.46 (DYNAMIC row format, the 8.0 default) rather than * read off a doc page: `varchar(768) UNIQUE` creates, `varchar(769) UNIQUE` @@ -18055,7 +18055,7 @@ export class SqlDriver implements IDataDriver { /** * The `varchar(n)` a KEYED text-family field should take, or `null` to leave - * the column TEXT (#11374). + * the column TEXT (commit d0e3a885b). * * `null` has exactly two causes, and both are deliberate non-events rather * than failures here: @@ -18139,7 +18139,7 @@ export class SqlDriver implements IDataDriver { * ⚠️ Deliberately mirrors {@link keyableTextLength} without sharing code * with it. The two families answer different questions — that one asks * "can this KEY?" and returns `null` for an unbounded field, this one asks - * "how wide is this column?" and returns 255 — and #11374's remaining half + * "how wide is this column?" and returns 255 — and the half commit d0e3a885b left open * may still reshape the text side. A shared helper would couple a settled * decision to an unsettled one. */ @@ -18163,7 +18163,7 @@ export class SqlDriver implements IDataDriver { /** * Turn MySQL's `ER_BLOB_KEY_WITHOUT_LENGTH` / `ER_TOO_LONG_KEY` into a message * that names the columns at fault and the remedy that actually applies - * (#11374, #12999). + * (commits d0e3a885b and ebcc34e89). * * ## TWO remedies, because the refusal has two causes * @@ -18172,7 +18172,7 @@ export class SqlDriver implements IDataDriver { * | **create** | the field declares no usable `maxLength` | declare one — the next create emits `varchar(n)` | * | **upgrade** | the field declares one; the COLUMN predates it and is still TEXT | convert the column by hand | * - * One message served both until #12999, and on the upgrade path both of its + * One message served both until commit ebcc34e89, and on the upgrade path both of its * halves were false: it diagnosed a missing declaration that was present, and * prescribed a declaration that was already made. That is not merely * imprecise — it fires once per boot on a production upgrade and reads as the @@ -18223,7 +18223,7 @@ export class SqlDriver implements IDataDriver { ? `Column(s) ${offenders.map((c) => `"${c}"`).join(', ')} are stored as TEXT` : 'One or more of its key columns is stored as TEXT'; - // #12999: the SAME refusal has two causes, and the message below is true of + // Commit ebcc34e89: the SAME refusal has two causes, and the message below is true of // only one of them. On CREATE the field really declares no usable bound, so // "declare `maxLength`" is the fix. On an UPGRADE the bound IS declared — // the additive sync never rewrites a column's type (#3728), so a column @@ -18325,7 +18325,7 @@ export class SqlDriver implements IDataDriver { * get different shadows. */ protected static hashShadowColumnFor(indexName: string): string { - // #13015: DELEGATES rather than re-deriving. The differ has to look for + // Commit cd1348802: DELEGATES rather than re-deriving. The differ has to look for // exactly the column the sync creates, and the two halves of that question // lived in different modules — which is how a healthy shadow-carried // UNIQUE came to be reported as destructive drift while the shadow column @@ -18374,7 +18374,7 @@ export class SqlDriver implements IDataDriver { * * - **Distinct values that share a long prefix both insert.** This is the * property that rules OUT the prefix-index alternative and the reason - * this route was chosen over it (maintainer ruling on #11374, + * this route was chosen over it (maintainer ruling recorded in commit 107bb4ba4, * 2026-08-24): measured, two distinct tokens sharing their first 191 * characters are BOTH accepted here, where `UNIQUE KEY (token(191))` * rejected the second as `ER_DUP_ENTRY` — a valid sign-in refused as a @@ -18402,7 +18402,7 @@ export class SqlDriver implements IDataDriver { * a crash. {@link explainHashShadowDuplicate} exists so the driver can tell * the two apart by reading the source columns back, and name whichever it is. * - * ## The NULL-safe organization key parts ride along (#12998) + * ## The NULL-safe organization key parts ride along (commit df1c75c4b) * * The shadow hashes the DECLARED key, not the raw columns. For a key part * `normalizeDeclaredIndex` marked NULL-safe (ADR-0120 D3 — the organization @@ -18427,7 +18427,7 @@ export class SqlDriver implements IDataDriver { if (!this.isMysql) return false; const shadow = SqlDriver.hashShadowColumnFor(indexName); const ref = (c: string) => `\`${c.replace(/`/g, '``')}\``; - // The DECLARED key part: NULL-safe parts in their COALESCE form (#12998), + // The DECLARED key part: NULL-safe parts in their COALESCE form (commit df1c75c4b), // plain parts as the bare column. const part = (c: string) => nullSafeColumns?.has(c) ? `COALESCE(${ref(c)}, '${GLOBAL_TENANT}')` : ref(c); @@ -18440,7 +18440,7 @@ export class SqlDriver implements IDataDriver { const addColumn = `ADD COLUMN ${ref(shadow)} VARBINARY(32) GENERATED ALWAYS AS (UNHEX(SHA2(${expr}, 256))) STORED`; const addKey = `ADD UNIQUE KEY ${ref(indexName)} (${ref(shadow)})`; - // #13015: the shadow column OUTLIVES the index it carries. Dropping a + // Commit cd1348802: the shadow column OUTLIVES the index it carries. Dropping a // UNIQUE key by name does not drop the generated column keyed by it, so // every path that drops and re-syncs — `recreate_index` above all — arrives // back here with the survivor still on the table. The unconditional @@ -18454,7 +18454,7 @@ export class SqlDriver implements IDataDriver { if (state === 'foreign') { // A real, non-generated column already owns the name. It is not ours to // drop — it may hold data — so this route is refused and the caller falls - // through to the named #11374 refusal, which is the honest outcome. + // through to the refusal commit d0e3a885b named, which is the honest outcome. this.logDurabilityFailure( `[sql-driver] cannot carry UNIQUE index '${indexName}' on "${tableName}" on a hash shadow — the ` + `column "${shadow}" already exists and is NOT a generated column, so it is not the driver's to ` + @@ -18468,7 +18468,7 @@ export class SqlDriver implements IDataDriver { await this.knex.raw(`ALTER TABLE ${ref(tableName)} ${addKey}`); } else if (state === 'stale') { // The survivor hashes a DIFFERENT key than metadata now declares — the - // pre-#12998 raw-column shadow is exactly this case. Reusing it would + // raw-column shadow from before commit df1c75c4b is exactly this case. Reusing it would // re-enforce the old constraint under the new name, which is the silent // wrong answer; the column carries no user data (it is derived), so it is // dropped and re-generated. Two statements rather than one ALTER: the @@ -18481,7 +18481,7 @@ export class SqlDriver implements IDataDriver { } // The boot log describes the key the shadow actually enforces — the // NULL-safe parts in their COALESCE spelling — so "carried" can be read - // literally (#12998). + // literally (commit df1c75c4b). const described = columns .map((c) => (nullSafeColumns?.has(c) ? `COALESCE(${c}, '${GLOBAL_TENANT}')` : c)) .join(', '); @@ -18501,13 +18501,13 @@ export class SqlDriver implements IDataDriver { } /** - * What is already sitting where this index's hash shadow goes (#13015)? + * What is already sitting where this index's hash shadow goes (commit cd1348802)? * * - `absent` — nothing; create the column and the key together. * - `reusable` — a generated column hashing EXACTLY the declared key. The * index that keyed it was dropped (a `recreate_index`, a * manual `DROP INDEX`, a half-applied migration); re-key it. - * - `stale` — a generated column hashing a DIFFERENT key. The pre-#12998 + * - `stale` — a generated column hashing a DIFFERENT key. The older (before commit df1c75c4b) * shadow over RAW columns is this case: reusing it would * re-enforce the OLD constraint under the new name — green, * silent, and wrong — so it is re-generated instead. @@ -18577,7 +18577,7 @@ export class SqlDriver implements IDataDriver { * * ## Ownership is ESTABLISHED, never assumed * - * Two refusals, in the shape of #13015's `foreign` guard — a column we have + * Two refusals, in the shape of commit cd1348802's `foreign` guard — a column we have * not proved is ours is left alone and named in the log, never dropped: * * - a column of this name that is **not generated** may hold user data; @@ -18715,7 +18715,7 @@ export class SqlDriver implements IDataDriver { if (sources.length === 0) return null; // Only the source columns the failing write actually supplied; a partial // update cannot be re-selected on columns it never mentioned. A NULL-safe - // key part (#12998) is exempt: the enforced key COALESCEs an absent or + // key part (commit df1c75c4b) is exempt: the enforced key COALESCEs an absent or // NULL value into the '__global__' bucket, so its key part is knowable // without the write mentioning the column. if ( @@ -18727,7 +18727,7 @@ export class SqlDriver implements IDataDriver { } let existing = 0; try { - // Re-select by the key the index ENFORCES, not by raw equality (#12998): + // Re-select by the key the index ENFORCES, not by raw equality (commit df1c75c4b): // a NULL-safe part compares through the same COALESCE the generation // expression carries (NULL and absent both land in the global bucket), // and plain parts use `<=>` — MySQL's NULL-safe equality; this whole @@ -18749,7 +18749,7 @@ export class SqlDriver implements IDataDriver { return null; } // Describe the key parts as enforced — NULL-safe parts in their COALESCE - // spelling — so the message names the actual constraint (#12998). + // spelling — so the message names the actual constraint (commit df1c75c4b). const described = sources .map((s) => (s.nullSafe ? `COALESCE(${s.column}, '${GLOBAL_TENANT}')` : s.column)) .join(', '); @@ -18809,7 +18809,7 @@ export class SqlDriver implements IDataDriver { * generation expression the server stores, so the disambiguating select * above filters on the same key the shadow was generated from. Per part: * the column identity, and whether the expression wraps it in the NULL-safe - * `COALESCE(col, …)` form (ADR-0120 D3 via #12998) — the read side must + * `COALESCE(col, …)` form (ADR-0120 D3 via commit df1c75c4b) — the read side must * compare through the same fold the enforced key applies. */ protected async hashShadowSourceColumns( @@ -18829,7 +18829,7 @@ export class SqlDriver implements IDataDriver { const expr = String(rows[0]?.GENERATION_EXPRESSION ?? rows[0]?.generation_expression ?? ''); // `unhex(sha2(`a`,256))`, `unhex(sha2(concat(`a`,0x1f,`b`),256))`, or with // a NULL-safe part: `…concat(coalesce(`org`,_utf8mb4'__global__'),0x1f,`b`)…` - // (#12998). #13015 moved the parse itself next to the shadow vocabulary + // (commit df1c75c4b). Commit cd1348802 moved the parse itself next to the shadow vocabulary // in `schema-drift.ts`: the differ reads the same expression to decide // whether a shadow-carried index enforces what metadata declares, and two // copies of this regex would be two answers to one question. @@ -19214,7 +19214,7 @@ export class SqlDriver implements IDataDriver { * is what SQLite's own JSON1 functions operate on, so this is the type the * database actually means. * - * That exposure is the one #12380 had to defeat on this driver's SQLite half + * That exposure is the one commit 4045b954d had to defeat on this driver's SQLite half * by making the `Field.json` codec injective. This change removes it at the * ROOT for new columns instead of encoding around it. * @@ -19245,7 +19245,7 @@ export class SqlDriver implements IDataDriver { * * It changes what NEW columns are declared as. It never rewrites an existing * column: the schema sync is additive, and a legacy `json` column keeps its - * declared type, its NUMERIC affinity, and the #12380 encoding that defeats + * declared type, its NUMERIC affinity, and the commit 4045b954d encoding that defeats * it. Nothing starts reporting drift over the difference either — the base- * type finding in `schema-drift.ts` is gated on * `multiValueColumnTypeIsLoadBearing(dialect)`, which is `postgres || mysql` @@ -19418,7 +19418,7 @@ export class SqlDriver implements IDataDriver { // is enforced at the write seam, and the data-URI refusal goes away. case 'signature': case 'qrcode': { - // #11374: a text-family column that some declared index KEYS ON is + // Commit d0e3a885b: a text-family column that some declared index KEYS ON is // emitted as `varchar(maxLength)` rather than TEXT, whenever the field // declared a bound this dialect can key on. // @@ -20152,7 +20152,7 @@ export class SqlDriver implements IDataDriver { } } - // ── JSON field serialisation: ONE encoding, every dialect (#12380) ────── + // ── JSON field serialisation: ONE encoding, every dialect (commit 4045b954d) ────── // // `JSON.stringify` unconditionally, which is what Postgres and MySQL have // always done here. This DELETES the SQLite branch rather than adding one, @@ -20266,7 +20266,7 @@ export class SqlDriver implements IDataDriver { } if (this.isSqlite) { - // The exact inverse of `formatInput`'s `JSON.stringify` (#12380). Postgres + // The exact inverse of `formatInput`'s `JSON.stringify` (commit 4045b954d). Postgres // and MySQL need no arm here because their clients already parse a native // `json`/`jsonb` column; SQLite hands back the stored TEXT, so the driver // parses it. One codec, three dialects, same answer. @@ -20280,7 +20280,7 @@ export class SqlDriver implements IDataDriver { // // Nothing this driver writes can reach it: every new value on disk is the // output of `JSON.stringify`, so it parses by construction. It is the - // READ-SIDE REPAIR for rows written before #12380 — a pre-fix plain string + // READ-SIDE REPAIR for rows written before commit 4045b954d — a pre-fix plain string // was stored raw (`America/New_York`), and re-quoting it is exactly what // {@link backfillCanonicalJsonEncoding} does on the next `syncSchema`. // Keeping it here is the same posture `backfillCanonicalDatetimes` takes: @@ -20295,7 +20295,7 @@ export class SqlDriver implements IDataDriver { // INTEGER/REAL cell (a number, a boolean, or a number-like string eaten by // NUMERIC affinity) are collisions already resolved on disk. Those rows // read exactly as they read before this change — the class stops growing; - // it is not retroactively repaired. See the ruling recorded on #12380. + // it is not retroactively repaired. See the decision recorded in commit 4045b954d's message. const jsonFields = this.jsonFields[object]; if (jsonFields && jsonFields.length > 0) { for (const field of jsonFields) { @@ -20303,7 +20303,7 @@ export class SqlDriver implements IDataDriver { try { data[field] = JSON.parse(data[field]); } catch { - // Pre-#12380 row: keep the raw string, which IS its value. + // Row from before commit 4045b954d: keep the raw string, which IS its value. } } } From fad95aff731848bc407b300da2067aadc0c7a475 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 06:32:00 +0000 Subject: [PATCH 2/2] chore(changeset): patch for the driver-sql provenance-comment rewrite 57 of the 122 rewritten non-test lines ship verbatim in dist (index.d.ts, index.d.mts, index.js, index.mjs); a base-text rebuild differs in those 4 of 6 dist files and a restored-head rebuild is byte-identical. Claude-Session: https://claude.ai/code/session_017xfMoEjKUuSh2xYB8sCozp Co-authored-by: Claude --- .changeset/20595-driver-sql-provenance-anchors.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .changeset/20595-driver-sql-provenance-anchors.md diff --git a/.changeset/20595-driver-sql-provenance-anchors.md b/.changeset/20595-driver-sql-provenance-anchors.md new file mode 100644 index 00000000000..4dc2efb4013 --- /dev/null +++ b/.changeset/20595-driver-sql-provenance-anchors.md @@ -0,0 +1,15 @@ +--- +'@objectstack/driver-sql': patch +--- + +Provenance comments in `@objectstack/driver-sql` cite the commits and ADR that decided them, not tracker numbers that no longer resolve + +Clause-②: no + +Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub. +Each one now cites the commit in this repository's history that made the decision it describes, or the +ADR that records it (ADR-0104's 2026-09-05 addendum). Some of these docblocks sit on exported members, +so the reworded text appears in the published `index.d.ts` / `index.d.mts`, and comments that esbuild +keeps appear in the JavaScript output. + +Comment only: no export, type, error code, status, message text or runtime behaviour changes.