ADR-0119 D3 rules IDataEngine.batch? retired. This issue is the mechanical removal.
ADR renumbered. This issue originally cited ADR-0118. That record is now ADR-0119 (docs/adr/0119-plugin-reachable-transactions-and-honest-atomic-batch.md) — it merged the same day as an unrelated ADR-0118 (非用户 actor 的平台契约), and the earlier merge holds the number.
The finding
packages/spec/src/contracts/data-engine.ts:97-100:
/** * Batch Operations (Transactional) */batch?(requests: DataEngineRequest[],options?: {transaction?: boolean}): Promise;- No engine implements it.
ObjectQL has no batch method; there is no other engine in the tree. - No caller invokes it.
DataEngineRequest is imported by exactly one non-spec file — the contract declaring it. - The doc comment is three words, specifying nothing about partial failure, ordering, cross-object refs, rollback scope, or what
transaction: false means. Contrast the deliberate, evidenced optionality of its neighbours getDefaultDriverName?/getDriverByName? (:107-118), which name their implementer and their probing caller. - Its
DataEngineRequestSchema union (packages/spec/src/data/data-engine.zod.ts:706-717) even nests batch requests recursively — a shape nobody designed against because nobody built it. - The only "test" is
packages/spec/src/contracts/data-engine.test.ts:162-177, which builds an ad-hoc object literal with a batch property and asserts it is defined. It pins the type, not an implementation.
A declared capability that cannot be exercised is precisely ADR-0049's enforce-or-remove target. ADR-0119 D1 (transaction on IObjectQLEngine) and D4 (real atomic batchData) now cover its stated purpose in-process, and POST {basePath}/batch covers it on the wire.
Work
Follow the spec-property-retirement playbook, contract-member route — this is a TypeScript contract member, not an authorable Zod metadata key, so there is no retiredKey tombstone to add (nothing can "author" it; the removal is invisible to metadata authors and visible only to TS consumers).
- Delete the member at
data-engine.ts:97-100; drop the type-only test case at data-engine.test.ts:162-177. - Decide
DataEngineRequest / DataEngineBatchRequestSchema's fate (data-engine.zod.ts:694-717, 764) — if the union has no other live reader after the member goes, it retires with it; if the wire-side batch still uses part of it, keep exactly that part and say so. - Rebuild spec before running the generated-artifact check (
pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated) — check:api-surface reads dist, and a stale dist produces a phantom-removal diff. - Changeset carrying the FROM → TO migration text, since it ships to consumers as the package CHANGELOG: "
IDataEngine.batch? is removed. It was never implemented by any engine and had no callers. For in-process multi-write atomicity use IObjectQLEngine.transaction(cb); for a batch over one object use the metadata protocol's batchData with options.atomic: true; on the wire use POST {basePath}/batch." - Upgrade-guide entry per ADR-0087's removal discipline.
Refs: ADR-0119 D3, ADR-0049, #4612.
ADR-0119 D3 rules
IDataEngine.batch?retired. This issue is the mechanical removal.The finding
packages/spec/src/contracts/data-engine.ts:97-100:ObjectQLhas nobatchmethod; there is no other engine in the tree.DataEngineRequestis imported by exactly one non-spec file — the contract declaring it.transaction: falsemeans. Contrast the deliberate, evidenced optionality of its neighboursgetDefaultDriverName?/getDriverByName?(:107-118), which name their implementer and their probing caller.DataEngineRequestSchemaunion (packages/spec/src/data/data-engine.zod.ts:706-717) even nests batch requests recursively — a shape nobody designed against because nobody built it.packages/spec/src/contracts/data-engine.test.ts:162-177, which builds an ad-hoc object literal with abatchproperty and asserts it is defined. It pins the type, not an implementation.A declared capability that cannot be exercised is precisely ADR-0049's enforce-or-remove target. ADR-0119 D1 (
transactiononIObjectQLEngine) and D4 (real atomicbatchData) now cover its stated purpose in-process, andPOST {basePath}/batchcovers it on the wire.Work
Follow the
spec-property-retirementplaybook, contract-member route — this is a TypeScript contract member, not an authorable Zod metadata key, so there is noretiredKeytombstone to add (nothing can "author" it; the removal is invisible to metadata authors and visible only to TS consumers).data-engine.ts:97-100; drop the type-only test case atdata-engine.test.ts:162-177.DataEngineRequest/DataEngineBatchRequestSchema's fate (data-engine.zod.ts:694-717, 764) — if the union has no other live reader after the member goes, it retires with it; if the wire-side batch still uses part of it, keep exactly that part and say so.pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated) —check:api-surfacereadsdist, and a staledistproduces a phantom-removal diff.IDataEngine.batch?is removed. It was never implemented by any engine and had no callers. For in-process multi-write atomicity useIObjectQLEngine.transaction(cb); for a batch over one object use the metadata protocol'sbatchDatawithoptions.atomic: true; on the wire usePOST {basePath}/batch."Refs: ADR-0119 D3, ADR-0049, #4612.