Skip to content

Commit 179f0ae

Browse files
qq9340100claude
andauthored
chore(tests,tooling): rule the second driver-memory consumer and gate the census (#6664) (#6693)
Fixes #6664 Maintainer ruling 2026-08-08: Option A + Option C in one PR, Option B rejected. A — `packages/runtime/src/autonumber-seed-cross-side-parity.integration.test.ts` gets its own ruling block, inheriting #5704's Q2 = B: its schemaless arm is structural (InMemoryDriver declares `supports = {}`, so the engine's fallback seeding owns the counter; SqlDriver advertises the capability and answers from its own sequence bootstrap, which is the other arm of the same `toBe()`). The driver-split file's census is restated as two ruled consumers. C — `scripts/check-driver-memory-census.mjs` + `scripts/driver-memory-census.ledger.json` replace the prose census with a ledger and a gate: every module binding of `@objectstack/driver-memory` in a tracked TS file and every package.json dependency declaration must be ledgered, every ledger entry must still be live, each ruled file must still carry its ruling markers, and each must state the ruled COUNT verbatim — so the sentence and the set can no longer drift apart. The gate polices the retirement programme's bookkeeping only; nothing here invests in the driver (#5499 freeze). Claude-Session: https://claude.ai/code/session_01K94yzy5CVgC2JtrqYAuDk2 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0c49b50 commit 179f0ae

6 files changed

Lines changed: 927 additions & 14 deletions

File tree

.github/workflows/lint.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,36 @@ jobs:
492492
- name: Resume-authority declaration gate
493493
run: pnpm check:resume-authority-declared
494494

495+
# driver-memory census gate (#6664, from #5704 / #5499). #5499 froze
496+
# investment in `@objectstack/driver-memory`; #5704 migrated the project's
497+
# test backends to sqlite `:memory:` and ruled that one test file keeps the
498+
# driver on purpose. The programme's enforcement was a PROSE CENSUS — a
499+
# sentence in that file claiming it was the only permanent test consumer in
500+
# the repository, backed by #5704/#5784 renaming every look-alike local stub
501+
# to `makeStubDriver` so a grep would land on real consumers only. The grep
502+
# is a good handle; the sentence describing what it should find is not. It
503+
# expired silently the first time the hand-edit step was skipped: #6468
504+
# (PR #6553) added a second importer with no ruling block, named nowhere in
505+
# the census it invalidated, and the two ways that misleads are opposite —
506+
# delete the other file's schemaless arm as a "leftover", or take it as
507+
# implicitly covered so a THIRD arrival is never disposed of either. The
508+
# census is now a ledger (scripts/driver-memory-census.ledger.json) with a
509+
# gate reading it: every module binding and every package.json declaration
510+
# must be ledgered, every ledger entry must still be live, each ruled file
511+
# must still carry its ruling markers, and — the half a sentence can never
512+
# do for itself — each must state the ruled COUNT verbatim, so changing the
513+
# set makes both sentences fail until they are rewritten. Static AST over
514+
# tracked sources (positions, not text: a comment naming the package and the
515+
# bundler externals entry in packages/runtime/tsup.config.ts are mentions,
516+
# not arrivals), no build needed, so it belongs in this job. Runs its own
517+
# --self-test first: the detector can be broken while the census is fine,
518+
# and a scan that stops matching would report OK while reading nothing
519+
# (#4868's family — DISCOVERED refuses an empty scan for that reason).
520+
# It polices the retirement programme's bookkeeping; it is not investment in
521+
# the driver, which stays frozen under #5499.
522+
- name: driver-memory census gate
523+
run: pnpm check:driver-memory-census
524+
495525
# Merge-driver wiring gate (#6008, from #4675 / #4868). `merge=os-regen`
496526
# is what stops generator-owned artifacts (spec-changes.json, the ADR-0087
497527
# registries, the api-surface baselines) from text-merging into a

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"check:type-check-coverage": "node scripts/check-type-check-coverage.mjs --self-test && node scripts/check-type-check-coverage.mjs",
7474
"check:type-check-debt": "node scripts/check-type-check-coverage.mjs --self-test && node scripts/check-type-check-coverage.mjs --re-measure",
7575
"check:driver-conformance": "node scripts/check-driver-conformance.mjs --self-test && node scripts/check-driver-conformance.mjs",
76+
"check:driver-memory-census": "node scripts/check-driver-memory-census.mjs --self-test && node scripts/check-driver-memory-census.mjs",
7677
"check:engine-double-contract": "node scripts/check-engine-double-contract.mjs --self-test && node scripts/check-engine-double-contract.mjs",
7778
"check:resume-authority-declared": "node scripts/check-resume-authority-declared.mjs --self-test && node scripts/check-resume-authority-declared.mjs",
7879
"check:spec-parsed-alias": "node scripts/check-spec-parsed-alias.mjs --self-test && node scripts/check-spec-parsed-alias.mjs",

packages/runtime/src/autonumber-seed-cross-side-parity.integration.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,51 @@
3030
* the same fixture rows.
3131
*/
3232

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

packages/runtime/src/sandbox/undeclared-field-write-driver-split.integration.test.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,21 @@
4646
* test consumer of it that #5704 RULED permanent. It is NOT a migration
4747
* leftover — do not "finish the job" by deleting or replacing it.
4848
*
49-
* (This block used to say "the only permanent test consumer in the repository".
50-
* That census expired without anyone editing it: `#6468`'s
51-
* `autonumber-seed-cross-side-parity.integration.test.ts`, in this same
52-
* package, imports the driver too and is not covered by #5704's ruling. Its
53-
* disposition is filed as #6664. The sentence now claims what it can defend: a
54-
* RULING about this file, not a count of the repository.)
49+
* #6664 census: 2 ruled consumers — this file, and
50+
* `../autonumber-seed-cross-side-parity.integration.test.ts` (#6468's
51+
* engine-vs-driver autonumber convergence pin, ruled permanent on #6664 by
52+
* maintainer 2026-08-08, inheriting the same Q2 = B). That block carries its own
53+
* ruling; read it there rather than assuming this one covers it.
54+
*
55+
* This block used to say "the only permanent test consumer in the repository",
56+
* and that census expired without anyone editing it — the autonumber test
57+
* arrived after #5704's survey and nothing was watching. So the count stopped
58+
* being prose: `pnpm check:driver-memory-census` reads
59+
* `scripts/driver-memory-census.ledger.json` and fails on any declaration of the
60+
* driver the ledger does not cover, in either direction. A third arrival is now
61+
* refused at the gate, and changing the ruled SET makes both files' census
62+
* sentences fail until they are rewritten — which is the half a sentence could
63+
* never do for itself (#6664, ruling C).
5564
*
5665
* Why it has to stay: the whole point of this file is a PRODUCT divergence
5766
* between two driver families — writing an undeclared field is rejected as a
@@ -67,10 +76,14 @@
6776
* (defect fixes, feature work). Using it as a reference implementation is not
6877
* investment, and nothing here fixes or extends it. Ruling: #5704, maintainer
6978
* 2026-08-06, Q2 = B ("keep, in this one place, with a comment saying so").
70-
* Consequence, also ruled there: `packages/runtime`'s `driver-memory` devDep
71-
* stays for the long term. (That devDep now has a second importer in this
72-
* package as well — #6468's autonumber parity test — so removing this file's
73-
* import alone would no longer even drop the dependency. See #6664.)
79+
* Consequence, also ruled there: 「runtime 的 driver-memory devDep 长期保留(仅
80+
* 此一个消费点)」. Two words of that consequence have since moved, and the ledger
81+
* records both rather than leaving them to be re-derived: the declaration is in
82+
* `packages/runtime`'s `dependencies`, not `devDependencies` (beside `driver-sql`
83+
* and `driver-sqlite-wasm`, which this package declares for the same reason — the
84+
* datasource factory resolves them by dynamic import), and it now serves TWO
85+
* ruled consumers in this package rather than one, so removing this file's import
86+
* alone would not drop it.
7487
*
7588
* Everything else that used to look like a driver-memory test consumer was a
7689
* hand-written local stub whose NAME merely said "memory" — in packages that
@@ -103,11 +116,15 @@
103116
*
104117
* What a grep for the driver's DECLARATIONS finds in `packages/` after that
105118
* migration: this file, and #6468's `autonumber-seed-cross-side-parity`
106-
* integration test (unruled — #6664). Nothing in plugin-auth. The prose
107-
* MENTIONS that remain there — the identity-lane files explain the history
119+
* integration test — both ruled, both ledgered. Nothing in plugin-auth. The
120+
* prose MENTIONS that remain there — the identity-lane files explain the history
108121
* above in their own comments, because a pin has to say what it used to be
109-
* wrong about — are not consumers: retirement verification greps declarations,
110-
* not mentions, which is the distinction that makes the grep usable at all.
122+
* wrong about — are not consumers: retirement verification counts declarations,
123+
* not mentions. That distinction is what made the grep usable at all, and it is
124+
* now the gate's rule too: `check:driver-memory-census` classifies by module
125+
* position (AST, not text), so a comment naming the package and the bundler
126+
* externals entry in `packages/runtime/tsup.config.ts` are reported as mentions
127+
* and never as arrivals.
111128
*/
112129

113130
import { describe, it, expect, afterEach } from 'vitest';

0 commit comments

Comments
 (0)