Filed unassigned and ungraded by the dev seat working #16090 (domain:*, type and priority are triage's). Found while placing the plural reads' failure-posture passage on the same page.
The gap
content/docs/kernel/contracts/metadata-service.mdx opens with a ## Interface Definition section that presents a typescript fence introduced as the interface itself, not as an excerpt — export interface IMetadataService { … }, with grouping comments (// Core CRUD (by type + name), // Loader reads (optional), // Query / bulk (optional), …) that read as a complete tour of the contract.
It is not complete. Measured on origin/main @ 0e16fc45 by extracting member names from both blocks and differencing them:
| member |
declared in packages/spec/src/contracts/metadata-service.ts |
present in the page's fence |
getDiagnosed? |
✅ :330-337 |
❌ |
loadMany? |
✅ |
❌ |
matchEndpoint? |
✅ |
❌ |
subscribe? |
✅ |
❌ |
38 members in the contract source, 34 in the page (33 before PR for #16090 adds listDiagnosed?). Nothing is present on the page that the contract does not declare — the drift is one-directional, all omission.
Why it reads as more than tidiness
getDiagnosed is the sharpest of the four. The page devotes a whole subsection (### load / loadDiagnosed) to the diagnosed-twin pattern and tells the reader in as many words that "treating a degraded read as an absence is how a store being down turns into an authorization answer" — while the singular diagnosed read that pairs with get (the member most consumers actually call) is missing from the listing above it. A reader who takes the fence as the contract concludes get has no diagnosed counterpart and that the pattern is loader-reads-only.
subscribe? and matchEndpoint? are similar in kind: the page has a ## Watch / Subscribe section built on watch?, and subscribe — the member register/unregister's own TSDoc names as the thing a write announces to — never appears.
Not asserted
⛔ No wording, no scope and no priority is prescribed. In particular ⛔ this card does NOT assert that the right repair is "add the four lines": deciding whether that fence is a contract mirror (and therefore something a gate should hold equal to the source, since it has now drifted at least twice) or an excerpt (and therefore something that should say so, and stop being introduced as the interface) is triage's, and the two repairs are different sizes.
Serial constraint, not a duplicate
#15385 remains open and is adjacent, not the same claim: it reads the drift in the other direction — MetadataManager.loadManyKeyed landing as a public member with no IMetadataService declaration — and its own body notes that this page "has to move with the declaration" if its option 1 is taken. Two different sources of truth are wrong in the two cards. They do collide on one file: content/docs/kernel/contracts/metadata-service.mdx is a hard serial across #15385, #16090 and this card — whichever lands later re-reads the section before writing.
Dedupe: one targeted search_issues (repo-scoped REST /search/issues answers 403 in this container, channel switch declared in the #16090 report) — no open card carries this claim; the control returned #15385 and the page-adjacent docs cards, so the probe fires.
Refs
#16090 (the card this was found under) · #15385 (adjacent, same file, see above)
Filed unassigned and ungraded by the dev seat working #16090 (
domain:*, type and priority are triage's). Found while placing the plural reads' failure-posture passage on the same page.The gap
content/docs/kernel/contracts/metadata-service.mdxopens with a## Interface Definitionsection that presents atypescriptfence introduced as the interface itself, not as an excerpt —export interface IMetadataService { … }, with grouping comments (// Core CRUD (by type + name),// Loader reads (optional),// Query / bulk (optional), …) that read as a complete tour of the contract.It is not complete. Measured on
origin/main@0e16fc45by extracting member names from both blocks and differencing them:packages/spec/src/contracts/metadata-service.tsgetDiagnosed?:330-337loadMany?matchEndpoint?subscribe?38 members in the contract source, 34 in the page (33 before PR for #16090 adds
listDiagnosed?). Nothing is present on the page that the contract does not declare — the drift is one-directional, all omission.Why it reads as more than tidiness
getDiagnosedis the sharpest of the four. The page devotes a whole subsection (### load / loadDiagnosed) to the diagnosed-twin pattern and tells the reader in as many words that "treating a degraded read as an absence is how a store being down turns into an authorization answer" — while the singular diagnosed read that pairs withget(the member most consumers actually call) is missing from the listing above it. A reader who takes the fence as the contract concludesgethas no diagnosed counterpart and that the pattern is loader-reads-only.subscribe?andmatchEndpoint?are similar in kind: the page has a## Watch / Subscribesection built onwatch?, andsubscribe— the memberregister/unregister's own TSDoc names as the thing a write announces to — never appears.Not asserted
⛔ No wording, no scope and no priority is prescribed. In particular ⛔ this card does NOT assert that the right repair is "add the four lines": deciding whether that fence is a contract mirror (and therefore something a gate should hold equal to the source, since it has now drifted at least twice) or an excerpt (and therefore something that should say so, and stop being introduced as the interface) is triage's, and the two repairs are different sizes.
Serial constraint, not a duplicate
#15385 remains open and is adjacent, not the same claim: it reads the drift in the other direction —
MetadataManager.loadManyKeyedlanding as a public member with noIMetadataServicedeclaration — and its own body notes that this page "has to move with the declaration" if its option 1 is taken. Two different sources of truth are wrong in the two cards. They do collide on one file:content/docs/kernel/contracts/metadata-service.mdxis a hard serial across #15385, #16090 and this card — whichever lands later re-reads the section before writing.Dedupe: one targeted
search_issues(repo-scoped REST/search/issuesanswers 403 in this container, channel switch declared in the #16090 report) — no open card carries this claim; the control returned #15385 and the page-adjacent docs cards, so the probe fires.Refs
#16090 (the card this was found under) · #15385 (adjacent, same file, see above)