Skip to content

test(driver-sql): the three live-MySQL NULL-safe shadow suites model a pre-18 store - #25142

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-25131-mysql-fixtures-pre18-tenant-column
Oct 21, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-25131-mysql-fixtures-pre18-tenant-column

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Refs #25131

Clause-②: no (test fixtures only: no response, status, error, outcome or export moves)
Metadata-protocol: none

main's hourly full run is red in Temporal Conformance (live PG + MySQL), in the step "Run driver-sql suite against both live servers". This PR changes only the fixture setup of the three live-MySQL suites that fail there. No production file moves, and no test or assertion is narrowed, skipped or deleted.

What is red, measured on 60b42cd0b7 and on today's abc25a35

7 failures, not the 6 the card names. The card's count was read on fccbd9d0d5, before #24893 (d5d8146012, 18.x step 7b-1 + 7b-2) landed. The hourly run's own log at 60b42cd0b7 (run 39683348463, job 119511306969) lists 7. My local reproduction below lists the same 7, by name.

File Failing test What failed
sql-driver-12998-shadow-null-safe-key.test.ts collides two NULL-organization rows under an org-scoped shadow unique the generation expression has no coalesce
12998 diagnoses existing NULL-org duplicates instead of failing the boot unexplained setup insert: Column 'organization_id' cannot be null
12998 names a NULL-organization duplicate in declared terms, never as a collision setup insert: Field 'organization_id' doesn't have a default value
12998 counts the sixth conflicting group in the shared "more group(s)" tail setup insert: Column 'organization_id' cannot be null
sql-driver-13015-shadow-carried-index-drift.test.ts survives "os migrate apply --allow-destructive" over every reported entry setup insert: Column 'organization_id' cannot be null
13015 reports and repairs a shadow that hashes the raw columns no drift reported for a raw shadow
sql-driver-15479-shadow-plain-unique-duplicates.test.ts leaves the NULL-safe arm saying the NULL-safe thing setup insert: Column 'organization_id' cannot be null

There are two causes, not one.

The change (fixture setup only, the three files)

  • The org-scoped index these tests use is declared in its 18.0 form: fields: ['organization_id', 'v'], unique: true, nullSafeColumns: ['organization_id'].
  • asPre18TenantColumn(driver, table) follows each initObjects whose table then receives NULL-organization rows: seven call sites. This is the pattern 7b-0 wired into the other driver-sql suites.
    • In 15479 the call is conditional on the seed row carrying organization_id: null. Only the control does; the plain and global arms stamp an organization or have no tenant column.
  • Every assertion is untouched.

Measured before the edit

  • The second initObjects does not restore NOT NULL. A scratch probe against the built driver on live MySQL 8.0 read information_schema.COLUMNS.IS_NULLABLE:
    • after the first initObjects: NO;
    • after asPre18TenantColumn: YES;
    • after a second initObjects with the index, on the same driver (12998 dirty/tail and the 15479 shape): YES;
    • after a second initObjects on a new driver (the 13015 apply shape): YES;
    • detectManagedDrift then reports [], and applyMigrationEntries(..., { allowDestructive: true }) leaves it YES.
    • So no second relax is needed anywhere.
  • Why the PG cell passes: none of the three suites has a PostgreSQL cell. The hash-shadow route exists only because MySQL refuses a key part over its 768-character ceiling; PostgreSQL and SQLite never take it. The PG-gated suites that seed organization-less rows were wired with asPre18TenantColumn by 7b-0.
  • Census of the live-gated driver-sql suites:
    • Static pass: 79 test files use declareDialectCell, a dialect cell or an OS_TEST_*_URL. Only these three insert organization-less rows without the relax. The one other hit, sql-driver-tenant-column-not-null.test.ts, inserts NULL on purpose to pin 7b-0's refusal.
    • Measured pass: the full live run below. 242/242 files are green, so no fourth file surfaces.

Verification

Live MySQL 8.0 (mirror.gcr.io/library/mysql:8.0, SET GLOBAL time_zone = '+08:00') and PostgreSQL 16 (mirror.gcr.io/library/postgres:16, timezone Asia/Shanghai), both in local containers, with CI's environment: TZ=America/New_York, OS_TEST_MYSQL_URL, OS_TEST_POSTGRES_URL and OS_EXPECT_LIVE_DIALECT_MATRIX=1.

Run Head Result
The three files, live, before the edit abc25a35 Test Files 3 failed (3), Tests 7 failed / 12 passed (19): the 7 above
The three files, live, after the edit e4c6eaf7c Test Files 3 passed (3), Tests 19 passed (19)
pnpm --filter @objectstack/driver-sql test, live PG + MySQL (CI's step) e4c6eaf7c Test Files 242 passed (242), Tests 5688 passed / 2 skipped (5690), exit 0
pnpm --filter @objectstack/driver-sql test, default (no live servers) e4c6eaf7c Test Files 230 passed / 12 skipped (242), Tests 3742 passed / 212 skipped, exit 0
pnpm --filter @objectstack/driver-sql typecheck e4c6eaf7c exit 0. tsc --listFiles lists all three files.

Gates on e4c6eaf7c. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 54 families.

  • All 54 ran, with each exit code captured before any pipe.
  • 52 exited 0. check:dual-build-cjs-loads and check:lean-entry-closure exited 3 (PREREQUISITE NOT MET); after pnpm exec turbo run build --concurrency=2 (77/77), both exit 0.
  • --ran reconciliation: "54 derived, 54 run, 0 NOT-MEASURED, 0 UNRUN", a DERIVED zero.
  • origin/main was merged before this PR opened: already up to date at abc25a35.

Changeset. skip-changeset: @objectstack/driver-sql ships files: [dist, README.md, CHANGELOG.md]. Built-dist grep: the test fixture symbols hit 0 files, and the control relax_not_null hits 4.

The hourly run. Temporal Conformance (live PG + MySQL) runs only on push, schedule and dispatch, never on a PR or in the queue. This PR's CI therefore does not run the live cell. The local live run above is its proof here, and the next hourly full run after merge is the proof on main.

Acceptance notes


Generated by Claude Code

…a pre-18 store

Since 7b-0 a table initObjects creates holds organization_id NOT NULL, and
since 7b-2 a unique: 'organization' declaration keys the plain tenant
column. The 12998, 13015 and 15479 live cells pin the NULL-safe hash-shadow
arm, so their fixtures now declare the index in its 18.0 form (an input
carrying nullSafeColumns, honoured verbatim) and relax the tenant column
with asPre18TenantColumn before writing NULL-organization rows.

Claude-Session: https://claude.ai/code/session_018gewcgUaNUX9hMkxeP2HE2
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json abc25a3536e2f00cc55ee6745320cb8f7209c459 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: e4c6eaf7c0
Local-runs: none

Scope: the net diff against the merge base (3 files, +67/−8), all fixture setup in packages/drivers/driver-sql/src:

  • sql-driver-12998-shadow-null-safe-key.test.ts;
  • sql-driver-13015-shadow-carried-index-drift.test.ts;
  • sql-driver-15479-shadow-plain-unique-duplicates.test.ts.

Read with them:

① Derived judgments

  • The failure is 7 tests, not the card's 6, and the cause is two-fold: right.
  • The fix models the store these tests are about, and every assertion stays.
  • Going beyond the claim's route is right, and is taken under the dispatch's "按实测修" clause. asPre18TenantColumn alone would green five of the seven at most. Stamping an organization on the seeds (the dev's option C) would remove the NULL-organization rows that are each test's subject. Rewriting the assertions (B) is forbidden by the card.
  • A second initObjects does not restore NOT NULL, measured on live MySQL: the column stays nullable after a second initObjects on the same or a new driver, detectManagedDrift reports nothing, and applyMigrationEntries with allowDestructive leaves it nullable. So no second relax is owed.
  • The proof is a live run, not a reading. In local containers with CI's recipe (MySQL 8.0 at +08:00, PostgreSQL 16, TZ=America/New_York, OS_EXPECT_LIVE_DIALECT_MATRIX=1):
    • before, on abc25a35: 7 failed and 12 passed across the three files;
    • after, on e4c6eaf7c: 19 of 19 passed, and the full live driver-sql suite passed 5688 with 2 skipped, 242/242 files;
    • the default run passed 3742 with 212 skipped, and the typecheck exited 0.

② Semver level

  • No changeset: test files only. The PR carries skip-changeset, and Check Changeset passed.
  • The PR body carries the claim's Clause-②: no (test fixtures only: …) line verbatim at a line start, and Metadata-protocol: none.

③ Boundary flags

  • Card lifecycle: the body says Refs #25131, with no closing keyword. The generated card closes on the next green hourly run, and that run is also the in-CI proof, since Temporal Conformance does not run on a PR or in the merge queue.
  • Cross-lane: none. All three files are driver-sql's.
  • Not governed: check-governed-merges matched 0 of 3 paths; +67/−8.
  • git merge-tree --write-tree against today's origin/main (abc25a3536) is clean.
  • Deviations, all accepted:
    • the 18.0-form index declaration beyond the claim's route (see ①);
    • the count, 7 not 6;
    • the base abc25a35 (one plugin-auth commit past the dispatch's 60b42cd0b7);
    • the AGENTS.md commit trailers and session-URL footer;
    • the seat-held PR subscription.
  • Open questions: one, answered A above.
  • Out of scope: the card's own count (6 vs 7) is noted in the PR and files no card.
  • CI on e4c6eaf7c0: 8 of 39 check-runs still running at this read. The ACCEPT waits for green.

Implemented-by: claude/issue-25131-mysql-fixtures-pre18-tenant-column
Reviewed-by: session_01JtSQQ3EWsbNPzyYMug1tXy

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T23:17Z · ACCEPT

Head: e4c6eaf7c0. It carries the fixture setup in three live-MySQL driver-sql suites.

Card #25131 (p1, bug, area:devpath; main's hourly full run red; triage 6322801126): claim 6327765912, dispatch 6327806493. Dev report: 6328392278.

Item Reading
Shape Draft PR → main. The body opens Refs #25131, with no closing keyword: the generated card closes on the next green hourly run. 3 files, +67/−8. Not governed: check-governed-merges matched 0 of 3 paths.
Scope Seven live-MySQL tests stop failing in their setup. Five failed on 7b-0's NOT NULL tenant column. Two failed because 7b-2 no longer produces the NULL-safe shadow from unique: 'organization'. The fixtures now declare the org-scoped unique in its pre-18 NULL-safe form (nullSafeColumns: ['organization_id'], honoured verbatim) and call asPre18TenantColumn after initObjects. Every assertion stays.
Seat's own read The nullSafeColumns input is #24893's own spelling for the retained path in the driver-turso suites, and four other driver-sql suites on main already declare it. A second initObjects was measured not to restore NOT NULL. No test, cell or assertion is skipped, narrowed or deleted.
Review TIER_DEFAULT. Record 6328472119 is PASS on this head.
Declaration No changeset (test files only; skip-changeset, Check Changeset passed). Clause-②: no (test fixtures only: …) and Metadata-protocol: none at line starts on the PR body.
Cross-lane None.
Gates Dev at e4c6eaf7c: 54 derived, 54 run, all exit 0 (two re-run after the full build). Live, in local containers with CI's recipe: before, 7 failed and 12 passed in the three files; after, 19/19, and the full live driver-sql suite passed 5688 with 2 skipped (242/242 files). The default run passed 3742 with 212 skipped, and the typecheck exited 0.
CI At this read on e4c6eaf7c0: ci-failure GREEN, all 41 check-runs completed, none failed. Temporal Conformance does not run on a PR or in the merge queue, so the next hourly full run after the merge is the in-CI proof. git merge-tree against today's origin/main (abc25a3536) is clean.

Disposition:

  • open_questions: one, answered A: model the pre-18 store, keep every assertion.
  • deviations: all accepted:
    • the 18.0-form index declaration beyond the claim's route, under 按实测修;
    • 7 failures, not 6;
    • the base abc25a35;
    • the AGENTS.md trailers and footer;
    • the seat-held subscription.
  • out_of_scope_findings: the card's own count, noted in the PR, no card.

Landing: ordinary queue (pr_ready + automerge_enable through the relay). After the merge, the seat reads the next hourly full run. Green closes #25131. Red is this card's to root-cause again.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 21, 2026 23:18
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 21, 2026 23:18
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 21, 2026
Merged via the queue into main with commit 4c7dcb4 Oct 21, 2026
47 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-25131-mysql-fixtures-pre18-tenant-column branch October 21, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants