Skip to content

feat(verify): reusable checkReadCoercion driver conformance helper + cross-driver test#2671

Merged
os-zhuang merged 4 commits into
mainfrom
claude/read-coercion-conformance
Jul 7, 2026
Merged

feat(verify): reusable checkReadCoercion driver conformance helper + cross-driver test#2671
os-zhuang merged 4 commits into
mainfrom
claude/read-coercion-conformance

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Why

A stored value must read back as its declared type on every driver: a boolean as a JS boolean (not the integer 0/1 SQLite stores), a json field as an object/array (not serialized text), an integer as a number. When two drivers disagree, code green on one silently breaks on the other.

This is the invariant behind the 2026-07-06 case_escalation incident: a boolean guard field != true read the field back as integer 1 on Turso, so 1 != true was always true and the flow self-triggered forever — while the local repro (memory / better-sqlite3, both of which coerce) was green in 6s. The storage-specific fixes live in each driver (driver-sql's formatOutput; cloud's driver-turso remote path — cloud PR #753, merged). This PR adds the shared, checked contract.

What

  • @objectstack/verify: new checkReadCoercion(driver) — a reusable, driver-agnostic conformance helper. Mirrors the existing checkLedger idiom: returns a list of problems (empty = conformant) with no test-runner dependency, and takes any driver structurally (CoercibleDriver), so out-of-tree drivers — e.g. cloud's driver-turso in remote mode — can run the identical contract against themselves. Reads back its own row by id so it's robust when the probe object already holds rows.
  • packages/dogfood: a cross-driver conformance test consumes the shared helper, running it against driver-sql (better-sqlite3 :memory:) and driver-memory (asserting toEqual([])) plus a negative check that a raw non-coercing driver yields 3 problems. (dogfood already tests through @objectstack/verify and runs as the Dogfood Regression Gate; drivers added as its devDeps.)
  • changeset: minor for @objectstack/verify (new public API).

Verification (built from source, run locally + CI green)

  • Dogfood suite 191 passed / 39 files incl. the new conformance test (both drivers → []; non-coercing stub → 3 problems).
  • turbo run build --filter=./packages/* 60/60 (no dependency cycle).
  • @objectstack/verify build incl. DTS clean; ESLint clean.
  • All 17 PR checks green.

Follow-up (separate, needs a framework SHA bump in cloud)

Cloud's driver-turso remote-read test can switch to importing checkReadCoercion from @objectstack/verify to run the identical contract against itself in remote mode — lands whenever cloud next bumps .framework-sha (not worth a dedicated bump on its own).

🤖 Generated with Claude Code

https://claude.ai/code/session_015EsQntpH9mUZqG7LAWzPAK

A stored value must read back as its declared type on every driver: a boolean
as a JS boolean (not the integer 0/1 SQLite stores), a json field as an
object/array (not serialized text), an integer as a number. When drivers
disagree, code green on one silently breaks on another.

This is the invariant behind the 2026-07-06 case_escalation incident (a boolean
guard `field != true` read the field back as integer `1` on Turso, so
`1 != true` was always true and the flow self-triggered forever, while the
memory/better-sqlite3 repro was green). The storage-specific fixes live in each
driver; this suite pins the shared contract so no framework driver — present or
future — can reintroduce the gap. Runs against driver-sql (better-sqlite3) and
driver-memory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015EsQntpH9mUZqG7LAWzPAK
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 7, 2026 5:09am

Request Review

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/dogfood, @objectstack/verify.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/permissions/authorization.mdx (via packages/dogfood)
  • content/docs/releases/implementation-status.mdx (via @objectstack/verify)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015EsQntpH9mUZqG7LAWzPAK
@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling labels Jul 7, 2026
Promote the read-coercion contract from a service-datasource-local test into a
reusable, driver-agnostic export in @objectstack/verify (mirrors checkLedger:
returns a problems list, empty = conformant, no test-runner dependency). Any
driver — including out-of-tree ones like cloud's driver-turso in remote mode —
can now run the identical contract against itself.

- verify: new checkReadCoercion(driver) + CoercibleDriver/ReadCoercionOptions.
- service-datasource: the cross-driver conformance test now consumes the shared
  helper (driver-sql better-sqlite3 + driver-memory), asserting `toEqual([])`.
- changeset: minor for @objectstack/verify (new public API).

Verified: service-datasource conformance 2 passed; helper flags a raw
non-coercing driver with 3 problems (boolean 1 / json text / numeric string);
verify build incl. DTS clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015EsQntpH9mUZqG7LAWzPAK
@github-actions github-actions Bot added dependencies Pull requests that update a dependency file size/m and removed size/s labels Jul 7, 2026
@os-zhuang os-zhuang changed the title test(service-datasource): pin cross-driver read-coercion conformance feat(verify): reusable checkReadCoercion driver conformance helper + cross-driver test Jul 7, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review July 7, 2026 04:49
…nce in dogfood

The prior commit added @objectstack/verify as a devDep of service-datasource,
but verify already depends on service-datasource (via runtime) — turbo flagged
the cycle and the build/typecheck/test jobs failed.

- Move the cross-driver conformance test out of service-datasource into
  packages/dogfood (which already dev-tests through @objectstack/verify and runs
  as the Dogfood Regression Gate); add driver-sql + driver-memory as dogfood
  devDeps. No cycle: drivers don't depend on verify/dogfood.
- Revert the service-datasource test + devDep.
- checkReadCoercion now reads back its own row by id (robust when the probe
  object already holds rows); the memory-driver test uses `persistence: false`
  so the probe never leaks to a shared on-disk snapshot across suites.

Verified: `turbo run build --filter=./packages/*` 60/60 (no cycle); full dogfood
suite 191 passed / 39 files (incl. the new conformance test: both drivers → [],
non-coercing stub → 3 problems); verify build incl. DTS clean; eslint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015EsQntpH9mUZqG7LAWzPAK
@os-zhuang
os-zhuang merged commit 3fd3576 into main Jul 7, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/read-coercion-conformance branch July 7, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants