test(objectql): type the batch-atomic driver double as IDataDriver, dropping the retired supports.transactions bit - #7261
Conversation
…and drop the retired `supports.transactions` bit
The snapshot driver in `protocol-batch-atomic.test.ts` authored
`supports: { transactions: true }` — a capability key RETIRED by #4634 and
tombstoned in `DriverCapabilitiesSchema` as `retiredKey(...)`. Neither
enforcement channel could fire on it: the literal was annotated `any`, so it was
never compared against `IDataDriver`, and nothing in this file parses the double
through `DriverInterfaceSchema`. The bit was inert — transaction use gates on
METHOD PRESENCE (`driver.beginTransaction`), which this double implements.
Rather than only deleting the key, the double is now annotated `IDataDriver`, so
`tsc` at the authoring site is a live channel again. That is the part that closes
the class instead of the instance: mocks get copied, and a copy of this one used
to inherit both the retired bit and the `any` that hid it. Verified by
re-authoring the key under the annotation — it now fails with TS2322 at the
literal, where previously it compiled silently.
Typing it cost three stubs for `IDataDriver` members these tests never reach
(`upsert`, `syncSchema`, `dropTable`); each throws rather than returning a
plausible value. No cast cascade — the package's measured TEST_DEBT count is
unchanged at 340 (recorded ceiling 355), identical to the pre-change baseline.
Two pins now state the gate explicitly so the next reader need not re-derive it:
the transactional path runs end to end against an EMPTY `supports`, and removing
`beginTransaction` alone makes the engine refuse with 501. `delete` on that
required member became TS2790 under the annotation, so it is now
`Reflect.deleteProperty` — identical at runtime, and the double stays cast-free.
Test-only; no behaviour change and no published surface touched.
Refs #6546, #4634, #4782
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 31355694872 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
|
Merge-queue ejection triage — per the bot's checklist above, before any re-queue. Verdict: not this PR. Confirmed-flaky signature, and NOT re-queueing. Filed as #7282. 1. The failure cannot be reached from this diffFailing test is
The queue log confirms a single failing task ( 2. Checklist item 2 is satisfied — same signature, another PR
3. The new fact — #7208's hardening was already in the build that failed here#7208's third-attempt patch raised these waits to It failed at a 20-second deadline. The "queue load makes the event late" diagnosis is therefore 4. Why I am not re-queueingThe bot's rule for this branch is explicit: flaky 实锤 ⇒ 开 issue 修/隔离那条测试;修好前重排只会再烧一轮全队列. This PR is green on its own merits — 23/23 checks passed on Generated by Claude Code |
|
PM call ( The 04:48Z triage above was right, and I am ⛔ not overturning any of its analysis. Its What I am overturning is one input, because it expired:
Measured just now: there is nothing behind it. Zero If it ejects again on the same signature, that is a third PR and a fifth run for #7282's evidence table, and I will hold it until #7282 lands rather than try a third time. Generated by Claude Code |
Closes #6546. Test-only.
What was wrong
The snapshot driver in
packages/objectql/src/protocol-batch-atomic.test.tsauthoredsupports: { transactions: true }— a capability key retired by #4634 and tombstoned inDriverCapabilitiesSchemaasretiredKey(...).Both enforcement channels were off:
const driver: any, so it was never compared againstIDataDriver;DriverInterfaceSchema.So the bit was inert. Transaction use gates on method presence (
driver.beginTransaction),which this double implements — the suite passed for the right reason and would have passed
identically with the key deleted.
What changed, and why it is not just a deletion
The card distinguishes this from its sibling #4782: there the retired keys were at least visible
to
tscas real TS2322 entries in the debt ledger. Here: anyerased the diagnostic entirely.Deleting the key alone would close the instance and leave the class open — mocks get copied, and a
copy of this one inherited both the retired bit and the
anythat hid it.So the double is now annotated
IDataDriver, which puts the tombstone back in front oftscat the authoring site.
Verified, not assumed. Re-authoring the key under the new annotation:
Before this PR the same line compiled silently.
Cost of typing it — measured, no cascade
Three
IDataDrivermembers these tests never reach needed stubs (upsert,syncSchema,dropTable). Each throws rather than returning a plausible value, so a future test cannot mistakea silent no-op for an exercised path. That is the whole cost; there is no cast cascade, and the
double remains free of
as any.@objectstack/objectqlexcludes its own tests fromtsc, so the relevant number is itsTEST_DEBTentry. Measured with the gate's own procedure (a sibling tsconfig that drops the testglobs), against a built workspace:
origin/main@0caf122)Unchanged, and well under the recorded ceiling of 355. The only errors remaining in this file are
three pre-existing
TS2554(registerObjectarity) that predate this change and are out of scopehere.
Evidence the suite passes for the right reason
The file already carried half the proof — a test that removes
beginTransactionand asserts theengine refuses with
501 NOT_IMPLEMENTED. Note that this passed while the mock still advertisedsupports: { transactions: true }, which is the direct demonstration that the bit decided nothing.This PR makes both halves explicit so the next reader does not have to re-derive them:
begin+commitobserved) against anempty
supports, withbeginTransactionpresent;delete plain.driver.beginTransactionbecameTS2790under the annotation (the member is requiredon
IDataDriver), so it is nowReflect.deleteProperty(...)— identical at runtime, and it avoidsreintroducing a cast.
pnpm exec vitest run src/protocol-batch-atomic.test.ts→ 7 passed (6 pre-existing + the new pin).Gates run locally
check:driver-conformancecheck:engine-double-contractcheck:type-check-coveragecheck:empty-changesetcheck:changeset-gate-self-testseslinton the changed fileChangeset
None, deliberately — this needs the
skip-changesetlabel rather than a changeset file.The diff is a single
*.test.tsfile: nosrc, no published surface, no behaviour change, so thereis nothing for a CHANGELOG entry to attach to.
check-empty-changeset.mjsis explicit that an emptychangeset is never the route here — it buys nothing the label does not and uniquely risks #4898
(
changesets/actiontakes itshasChangesets && !hasNonEmptyChangesetsbranch and silentlypublishes nothing). Nothing is declared breaking, so no ADR-0087 disposition applies.
Scope note
A repo-wide sweep for other
supports:literals spelling retired keys found none beyond the twodeliberate rejection fixtures (
packages/spec/src/data/driver.test.ts:317anddatasource.test.ts:60), which are correct as written. The sweep did surface a broader class —~64
any-annotated driver doubles inpackages/objectqlwhose tombstone diagnostic is off for thesame reason this one's was. None currently authors a retired bit, so nothing is red today. Filed
separately rather than folded in here.
Refs #6546, #4634, #4782.
Generated by Claude Code