Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,36 @@ jobs:
- name: Resume-authority declaration gate
run: pnpm check:resume-authority-declared

# driver-memory census gate (#6664, from #5704 / #5499). #5499 froze
# investment in `@objectstack/driver-memory`; #5704 migrated the project's
# test backends to sqlite `:memory:` and ruled that one test file keeps the
# driver on purpose. The programme's enforcement was a PROSE CENSUS — a
# sentence in that file claiming it was the only permanent test consumer in
# the repository, backed by #5704/#5784 renaming every look-alike local stub
# to `makeStubDriver` so a grep would land on real consumers only. The grep
# is a good handle; the sentence describing what it should find is not. It
# expired silently the first time the hand-edit step was skipped: #6468
# (PR #6553) added a second importer with no ruling block, named nowhere in
# the census it invalidated, and the two ways that misleads are opposite —
# delete the other file's schemaless arm as a "leftover", or take it as
# implicitly covered so a THIRD arrival is never disposed of either. The
# census is now a ledger (scripts/driver-memory-census.ledger.json) with a
# gate reading it: every module binding and every package.json declaration
# must be ledgered, every ledger entry must still be live, each ruled file
# must still carry its ruling markers, and — the half a sentence can never
# do for itself — each must state the ruled COUNT verbatim, so changing the
# set makes both sentences fail until they are rewritten. Static AST over
# tracked sources (positions, not text: a comment naming the package and the
# bundler externals entry in packages/runtime/tsup.config.ts are mentions,
# not arrivals), no build needed, so it belongs in this job. Runs its own
# --self-test first: the detector can be broken while the census is fine,
# and a scan that stops matching would report OK while reading nothing
# (#4868's family — DISCOVERED refuses an empty scan for that reason).
# It polices the retirement programme's bookkeeping; it is not investment in
# the driver, which stays frozen under #5499.
- name: driver-memory census gate
run: pnpm check:driver-memory-census

# Merge-driver wiring gate (#6008, from #4675 / #4868). `merge=os-regen`
# is what stops generator-owned artifacts (spec-changes.json, the ADR-0087
# registries, the api-surface baselines) from text-merging into a
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"check:type-check-coverage": "node scripts/check-type-check-coverage.mjs --self-test && node scripts/check-type-check-coverage.mjs",
"check:type-check-debt": "node scripts/check-type-check-coverage.mjs --self-test && node scripts/check-type-check-coverage.mjs --re-measure",
"check:driver-conformance": "node scripts/check-driver-conformance.mjs --self-test && node scripts/check-driver-conformance.mjs",
"check:driver-memory-census": "node scripts/check-driver-memory-census.mjs --self-test && node scripts/check-driver-memory-census.mjs",
"check:engine-double-contract": "node scripts/check-engine-double-contract.mjs --self-test && node scripts/check-engine-double-contract.mjs",
"check:resume-authority-declared": "node scripts/check-resume-authority-declared.mjs --self-test && node scripts/check-resume-authority-declared.mjs",
"check:spec-parsed-alias": "node scripts/check-spec-parsed-alias.mjs --self-test && node scripts/check-spec-parsed-alias.mjs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,51 @@
* the same fixture rows.
*/

/**
* ⚠️ `@objectstack/driver-memory` is imported here ON PURPOSE — ruled permanent
* by #6664 (maintainer 2026-08-08), inheriting #5704's Q2 = B ruling. It is NOT
* a migration leftover: do not "finish the driver-memory retirement" by deleting
* or replacing this arm.
*
* Why the arm is STRUCTURAL rather than a convenience. The cases below are a
* convergence assertion — one format, one set of stored rows, both real seeding
* implementations, `toBe(sqlValue)` on the engine's answer — so the two arms have
* to BE the two implementations, and which one answers is decided by the driver's
* declared capability, not by the test:
*
* - `InMemoryDriver` declares `supports = {}`, so the driver has no autonumber
* of its own and the ENGINE's fallback seeding owns the counter.
* - `SqlDriver` advertises the capability, so its own sequence bootstrap
* answers instead. That is the other arm, in `sqlDriverIssues()` below.
*
* Point the schemaless arm at sqlite `:memory:` (the #5704 migration target) and
* both arms become the same implementation: `toBe()` then passes because nothing
* distinguishes them, not because the two seeders agree. This family has paid for
* exactly that shape once — #5830 held `auth-contains-filter.test.ts` back from
* migration on the measurement that its SQL arm would have answered identically
* either way, and released it (#5893) only once #5702 gave that arm a real
* verdict again.
*
* Why the freeze does not forbid it: #5499 froze *investment* in driver-memory
* (defect fixes, feature work). Using it as a reference implementation is not
* investment, and nothing here fixes or extends it — #6468's fix landed in the
* engine and in `driver-sql`. The ruling says so in as many words (#5704,
* maintainer 2026-08-06): 「#5499 冻结令冻的是缺陷修复投入,不禁止作参照物使用」.
*
* Option B on #6664 — migrate this file — was ruled out rather than left open:
* it would spend measurement effort inside the freeze area for no user-visible
* payoff, against an arm that has no SQL equivalent to migrate TO.
*
* #6664 census: 2 ruled consumers — this file, and
* `sandbox/undeclared-field-write-driver-split.integration.test.ts`, which pins
* the other cross-family property (a DIVERGENCE, where this file pins a
* convergence). That count is no longer prose: `pnpm check:driver-memory-census`
* reads `scripts/driver-memory-census.ledger.json` and fails on any declaration
* of the driver the ledger does not cover, so a third arrival is refused at the
* gate instead of silently expiring this sentence — which is precisely what
* #6664 was filed about.
*/

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { ObjectQL } from '@objectstack/objectql';
import { InMemoryDriver } from '@objectstack/driver-memory';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,21 @@
* test consumer of it that #5704 RULED permanent. It is NOT a migration
* leftover — do not "finish the job" by deleting or replacing it.
*
* (This block used to say "the only permanent test consumer in the repository".
* That census expired without anyone editing it: `#6468`'s
* `autonumber-seed-cross-side-parity.integration.test.ts`, in this same
* package, imports the driver too and is not covered by #5704's ruling. Its
* disposition is filed as #6664. The sentence now claims what it can defend: a
* RULING about this file, not a count of the repository.)
* #6664 census: 2 ruled consumers — this file, and
* `../autonumber-seed-cross-side-parity.integration.test.ts` (#6468's
* engine-vs-driver autonumber convergence pin, ruled permanent on #6664 by
* maintainer 2026-08-08, inheriting the same Q2 = B). That block carries its own
* ruling; read it there rather than assuming this one covers it.
*
* This block used to say "the only permanent test consumer in the repository",
* and that census expired without anyone editing it — the autonumber test
* arrived after #5704's survey and nothing was watching. So the count stopped
* being prose: `pnpm check:driver-memory-census` reads
* `scripts/driver-memory-census.ledger.json` and fails on any declaration of the
* driver the ledger does not cover, in either direction. A third arrival is now
* refused at the gate, and changing the ruled SET makes both files' census
* sentences fail until they are rewritten — which is the half a sentence could
* never do for itself (#6664, ruling C).
*
* Why it has to stay: the whole point of this file is a PRODUCT divergence
* between two driver families — writing an undeclared field is rejected as a
Expand All @@ -67,10 +76,14 @@
* (defect fixes, feature work). Using it as a reference implementation is not
* investment, and nothing here fixes or extends it. Ruling: #5704, maintainer
* 2026-08-06, Q2 = B ("keep, in this one place, with a comment saying so").
* Consequence, also ruled there: `packages/runtime`'s `driver-memory` devDep
* stays for the long term. (That devDep now has a second importer in this
* package as well — #6468's autonumber parity test — so removing this file's
* import alone would no longer even drop the dependency. See #6664.)
* Consequence, also ruled there: 「runtime 的 driver-memory devDep 长期保留(仅
* 此一个消费点)」. Two words of that consequence have since moved, and the ledger
* records both rather than leaving them to be re-derived: the declaration is in
* `packages/runtime`'s `dependencies`, not `devDependencies` (beside `driver-sql`
* and `driver-sqlite-wasm`, which this package declares for the same reason — the
* datasource factory resolves them by dynamic import), and it now serves TWO
* ruled consumers in this package rather than one, so removing this file's import
* alone would not drop it.
*
* Everything else that used to look like a driver-memory test consumer was a
* hand-written local stub whose NAME merely said "memory" — in packages that
Expand Down Expand Up @@ -103,11 +116,15 @@
*
* What a grep for the driver's DECLARATIONS finds in `packages/` after that
* migration: this file, and #6468's `autonumber-seed-cross-side-parity`
* integration test (unruled — #6664). Nothing in plugin-auth. The prose
* MENTIONS that remain there — the identity-lane files explain the history
* integration test — both ruled, both ledgered. Nothing in plugin-auth. The
* prose MENTIONS that remain there — the identity-lane files explain the history
* above in their own comments, because a pin has to say what it used to be
* wrong about — are not consumers: retirement verification greps declarations,
* not mentions, which is the distinction that makes the grep usable at all.
* wrong about — are not consumers: retirement verification counts declarations,
* not mentions. That distinction is what made the grep usable at all, and it is
* now the gate's rule too: `check:driver-memory-census` classifies by module
* position (AST, not text), so a comment naming the package and the bundler
* externals entry in `packages/runtime/tsup.config.ts` are reported as mentions
* and never as arrivals.
*/

import { describe, it, expect, afterEach } from 'vitest';
Expand Down
Loading
Loading