Found incidentally while running the runtime put() caller census for #8006 (measurement only; no accept set was touched).
The observation
packages/metadata-core/src/contract-suite.ts exists so that one table of invariants holds for everyMetadataRepository implementation. Its own header says so, and the #7856/#7992 serialized-form pins were deliberately placed there rather than beside either bug for that reason.
Every call site of the suite, repo-wide:
packages/metadata-core/test/in-memory-repository.test.ts:8 runRepositoryContractTests('InMemoryRepository', …)
packages/metadata-fs/test/contract.test.ts:23 runRepositoryContractTests('FileSystemRepository', …)
Two implementations. SysMetadataRepository (packages/metadata-protocol/src/sys-metadata-repository.ts) is a third — it implements the same interface (put/get/getByHash/delete/history/watch), it calls hashSpec(body) itself at put(), and it is the implementation that backs the live runtime path. It is never handed to the suite.
Why this is worth a card rather than a shrug
Measured during the #8006 census, with put() instrumented across nine packages: of 1,729 runtime put() invocations observed, 561 went through SysMetadataRepository — including all four production put() call sites in the repo. The two implementations that are contract-tested carry the test traffic; the one that carries the production traffic is not held to the contract.
Concretely, the invariants that go unexercised for it include the ones #7992 added — put().version === get().hash and get().hash === hashSpec(get().body) — plus the older ConflictError / monotonic-seq / tombstone clauses. Note that #7992 fixed exactly this class of divergence in two implementations and found each had broken a different face of it, which is the argument that a third unexercised implementation is not safe by inspection.
⚠️Not a claim that it is broken. Nothing observed in the census suggests a defect; 561 invocations ran clean. This is an unexercised-surface finding, not a bug report.
Not necessarily a plain "add it to the suite"
SysMetadataRepository is engine-backed (it needs a sys_metadata table and an engine double), and it carries dimensions the suite's factory() shape does not model — state: 'draft' | 'active', packageId, org scoping. Whether it should be adapted into the existing suite, or whether the suite needs a narrower "serialized-form identity" slice that an engine-backed repository can be held to, is a design question and deliberately not decided here.
Provenance
Found incidentally while running the runtime
put()caller census for #8006 (measurement only; no accept set was touched).The observation
packages/metadata-core/src/contract-suite.tsexists so that one table of invariants holds for everyMetadataRepositoryimplementation. Its own header says so, and the #7856/#7992 serialized-form pins were deliberately placed there rather than beside either bug for that reason.Every call site of the suite, repo-wide:
Two implementations.
SysMetadataRepository(packages/metadata-protocol/src/sys-metadata-repository.ts) is a third — it implements the same interface (put/get/getByHash/delete/history/watch), it callshashSpec(body)itself atput(), and it is the implementation that backs the live runtime path. It is never handed to the suite.Why this is worth a card rather than a shrug
Measured during the #8006 census, with
put()instrumented across nine packages: of 1,729 runtimeput()invocations observed, 561 went throughSysMetadataRepository— including all four productionput()call sites in the repo. The two implementations that are contract-tested carry the test traffic; the one that carries the production traffic is not held to the contract.Concretely, the invariants that go unexercised for it include the ones #7992 added —
put().version === get().hashandget().hash === hashSpec(get().body)— plus the olderConflictError/ monotonic-seq/ tombstone clauses. Note that #7992 fixed exactly this class of divergence in two implementations and found each had broken a different face of it, which is the argument that a third unexercised implementation is not safe by inspection.Not necessarily a plain "add it to the suite"
SysMetadataRepositoryis engine-backed (it needs asys_metadatatable and an engine double), and it carries dimensions the suite'sfactory()shape does not model —state: 'draft' | 'active',packageId, org scoping. Whether it should be adapted into the existing suite, or whether the suite needs a narrower "serialized-form identity" slice that an engine-backed repository can be held to, is a design question and deliberately not decided here.Provenance
put()— the option-1 tightening deferred by #7856 #8006, maintainer ruling 2026-08-20 (comment5359013951).origin/main@801296050.finding, nopm:queue— this is an observation for triage to rank, not a queued task.