Found while doing #6043 (PR #6547). Filed separately per PD #10. Observation-class: no user-visible defect today — the gap is in coverage, not behavior.
Fact
register() in packages/metadata/src/metadata-manager.ts documents its announcement ordering as covering two writes:
// Announce last, once the write has landed in the registry and every
// writable loader — a subscriber that re-reads on the event must not
// race ahead of the data it is meant to observe.
register-notifies-watchers.test.ts is the file that pins this contract. After PR #6547 it asserts the registry half properly (synchronously, inside the watcher callback, at broadcast time). The writable-loader half is not asserted anywhere, and cannot be from that file as it stands:
- the fixture's only loader is
MemoryLoader, whose contract declares protocol: 'memory:';
register()'s persistence loop is gated on loader.contract.protocol !== 'datasource:' || !loader.contract.capabilities.write and continues otherwise;
- so
register() never saves to any loader in that file, and moving the announcement across the save loop changes nothing observable there.
Measured
Hoisting the notifyWatchers(...) block above the realtime publish and the writable-loader save loop — leaving the registry write in place — keeps the whole file green, both before and after PR #6547:
Test Files 1 passed (1)
Tests 15 passed (15)
That hoist violates the ordering the comment declares. Nothing reports it.
Why this is observation-class rather than a defect
A subscriber that re-reads via get() resolves against the in-memory registry, which outranks every loader, so it never observes the loader write — the half that IS pinned is the half consumers actually depend on. The unpinned half would only matter to a consumer reading through a loader directly, bypassing the registry, which nothing does today.
Shape of the fix (not chosen)
Needs a writable datasource: loader fixture whose save() records the store's state, then a synchronous peek at that store inside the watcher callback — the same shape #6043 used for the registry. metadata-manager-unregister-invalidate-order.test.ts already builds a writable datasource: loader backed by a real store and could be the donor.
Alternatively, if the loader half is deliberately NOT part of the guarantee, the comment on register() should be narrowed to say so — declared = enforced, in either direction.
Related
#6043 (where this surfaced), #3112 (origin of the test file), PR #6547.
Found while doing #6043 (PR #6547). Filed separately per PD #10. Observation-class: no user-visible defect today — the gap is in coverage, not behavior.
Fact
register()inpackages/metadata/src/metadata-manager.tsdocuments its announcement ordering as covering two writes:register-notifies-watchers.test.tsis the file that pins this contract. After PR #6547 it asserts the registry half properly (synchronously, inside the watcher callback, at broadcast time). The writable-loader half is not asserted anywhere, and cannot be from that file as it stands:MemoryLoader, whose contract declaresprotocol: 'memory:';register()'s persistence loop is gated onloader.contract.protocol !== 'datasource:' || !loader.contract.capabilities.writeandcontinues otherwise;register()never saves to any loader in that file, and moving the announcement across the save loop changes nothing observable there.Measured
Hoisting the
notifyWatchers(...)block above the realtime publish and the writable-loader save loop — leaving the registry write in place — keeps the whole file green, both before and after PR #6547:That hoist violates the ordering the comment declares. Nothing reports it.
Why this is observation-class rather than a defect
A subscriber that re-reads via
get()resolves against the in-memory registry, which outranks every loader, so it never observes the loader write — the half that IS pinned is the half consumers actually depend on. The unpinned half would only matter to a consumer reading through a loader directly, bypassing the registry, which nothing does today.Shape of the fix (not chosen)
Needs a writable
datasource:loader fixture whosesave()records the store's state, then a synchronous peek at that store inside the watcher callback — the same shape #6043 used for the registry.metadata-manager-unregister-invalidate-order.test.tsalready builds a writabledatasource:loader backed by a real store and could be the donor.Alternatively, if the loader half is deliberately NOT part of the guarantee, the comment on
register()should be narrowed to say so — declared = enforced, in either direction.Related
#6043 (where this surfaced), #3112 (origin of the test file), PR #6547.