Found while implementing #14205 (loader-held items keyed by the row key). Filed unassigned; deliberately NOT repaired in PR #14340 — see "Why not in that PR" below.
What #14205 established
A loader-held item's identity is the key its store holds it under, not body.name. register(type, name, data) takes the key as its ARGUMENT and assertMetadataRegisterContract explicitly allows a document with no name of its own, so a body is not required to name itself — an aggregated defineView container has none by design.
PR #14340 gives MetadataLoader an optional loadManyKeyed() returning (name, body) pairs, implements it on DatabaseLoader (row name column) and MemoryLoader (storage map key), and has MetadataManager prefer it. Loaders that do not implement it keep the previous body.name keying, which drops every nameless body.
The residue
Two shipped loaders do not implement it, so for them the defect stands as before:
packages/metadata/src/loaders/filesystem-loader.ts — loadMany() globs files and does items.push(data), discarding the file path it just read. The key IS available (the file's own name), so this one is repairable.packages/metadata/src/loaders/remote-loader.ts — loadMany() returns await response.json() from GET BASEURL/TYPE. The wire format carries bodies only, so no key exists to carry; exposing one is an HTTP-surface change, not a loader change.
Consequence in both cases: a metadata body with no top-level name, held by one of these loaders, is absent from MetadataManager.list() and from the endpoint index, and listDiagnosed() reports the short answer as complete (degraded: false) because nothing threw. That is exactly the failure #14205 describes, unrepaired for these two producers.
Why not in that PR
The bounded in-place exemption needs the repair to be mechanical with its correct shape already pinned by existing evidence. Neither is:
- FilesystemLoader's key is not simply the basename —
loadMany() takes caller-supplied patterns, walks nested directories, and reads several serializer formats. Which part of a path is the metadata key is a decision (findFile() and list() encode one answer; whether loadMany() must agree with it, and what happens for a nested path, is not settled anywhere I could find). Deriving it wrongly would key items under names nothing else uses, which is worse than today's honest drop. - RemoteLoader cannot be repaired on the loader side at all: the key is absent from the response. Any repair is a change to the metadata HTTP surface and needs its own ruling.
Suggested shape
Two separable pieces of work, probably two cards after triage:
- FilesystemLoader: rule what the key is for a file-held item (agreeing with
list() and findFile()), then implement loadManyKeyed(). - RemoteLoader: decide whether the remote metadata wire format should carry keys beside bodies. Contract-first — this is a producer-side question, and the consumer must not paper over it.
Neither is urgent in the way #14205 was: the measured production producer of nameless bodies is DatabaseLoader (a register()-written sys_metadata row), which PR #14340 repairs.
Related: #14205 (the exit that surfaced this), #13913.
Found while implementing #14205 (loader-held items keyed by the row key). Filed unassigned; deliberately NOT repaired in PR #14340 — see "Why not in that PR" below.
What #14205 established
A loader-held item's identity is the key its store holds it under, not
body.name.register(type, name, data)takes the key as its ARGUMENT andassertMetadataRegisterContractexplicitly allows a document with nonameof its own, so a body is not required to name itself — an aggregateddefineViewcontainer has none by design.PR #14340 gives
MetadataLoaderan optionalloadManyKeyed()returning (name, body) pairs, implements it onDatabaseLoader(rownamecolumn) andMemoryLoader(storage map key), and hasMetadataManagerprefer it. Loaders that do not implement it keep the previousbody.namekeying, which drops every nameless body.The residue
Two shipped loaders do not implement it, so for them the defect stands as before:
packages/metadata/src/loaders/filesystem-loader.ts—loadMany()globs files and doesitems.push(data), discarding the file path it just read. The key IS available (the file's own name), so this one is repairable.packages/metadata/src/loaders/remote-loader.ts—loadMany()returnsawait response.json()fromGET BASEURL/TYPE. The wire format carries bodies only, so no key exists to carry; exposing one is an HTTP-surface change, not a loader change.Consequence in both cases: a metadata body with no top-level
name, held by one of these loaders, is absent fromMetadataManager.list()and from the endpoint index, andlistDiagnosed()reports the short answer as complete (degraded: false) because nothing threw. That is exactly the failure #14205 describes, unrepaired for these two producers.Why not in that PR
The bounded in-place exemption needs the repair to be mechanical with its correct shape already pinned by existing evidence. Neither is:
loadMany()takes caller-suppliedpatterns, walks nested directories, and reads several serializer formats. Which part of a path is the metadata key is a decision (findFile()andlist()encode one answer; whetherloadMany()must agree with it, and what happens for a nested path, is not settled anywhere I could find). Deriving it wrongly would key items under names nothing else uses, which is worse than today's honest drop.Suggested shape
Two separable pieces of work, probably two cards after triage:
list()andfindFile()), then implementloadManyKeyed().Neither is urgent in the way #14205 was: the measured production producer of nameless bodies is
DatabaseLoader(aregister()-writtensys_metadatarow), which PR #14340 repairs.Related: #14205 (the exit that surfaced this), #13913.