Found while adding the canonical-key banner for #3906 (PR #5922). Not fixed there — different defect class, filed unassigned for triage.
content/docs/guide/layout.md states a PageHeaderProps key list that the contract contradicts, and a registration input list that packages/layout contradicts. Two claims, both measurable, both in the same blockquote.
Claim 1 — a retired key listed as declared, three live keys missing
content/docs/guide/layout.md:287:
PageHeaderProps — the contract for the canonical page:header node — declares
title / subtitle / icon / breadcrumb / actions / aria
Measured against the installed @objectstack/spec (PageHeaderProps.safeParse, values quoted from the parser's own verdict):
{ title: 'Accounts', icon: 'users' } → REJECTED, code=invalid_type path=["icon"], message: ``page:headerpropertyicon` was removed ... (ADR-0087 D2) — no renderer ever read it ...`. `icon` is a `retiredKey` tombstone on this shape, not a declared key.{ title: 'Accounts', subtitle: 'All accounts' } → OK, output keys ["title","subtitle","breadcrumb","recordChrome","showStar","showCopyId"]. The guide's list omits recordChrome, showStar and showCopyId.- Negative control,
{ title: 'Accounts', zzzNotAKey: 1 } → REJECTED unrecognized_keys, so the shape really is strict and the readings above mean something.
The sibling page already says the right thing — content/docs/layout/page-header.mdx lists title / subtitle / breadcrumb / actions / recordChrome / showStar / showCopyId / aria. So two docs pages disagree, and the guide is the wrong one. An author who trusts it writes icon on a canonical node and gets a parse failure naming a key the docs told them to use.
Claim 2 — the registration input list is two entries behind
Same blockquote, content/docs/guide/layout.md:288:
and page-header's registration declares only title and subtitle as authorable inputs
packages/layout/src/index.ts:121 declares four: title, subtitle, icon, actions — icon and actions were added deliberately (the registration's own comment cites objectui#3829 and objectui#3972, on renderer-read-point evidence). The word "only" is what makes this a false statement rather than an incomplete one.
Why no gate caught it
Neither claim lives in a code fence, so check-doc-component-types (type literals in code blocks) and check-doc-snippet-types (ts/tsx block compilation) are both structurally blind to it. content/docs/guide/layout.md is additionally in check-doc-snippet-types' UNGATED_DOCS debt list. Prose claims about a declared surface have no mechanical judge in this repo today — worth noting when sizing this, because the same drift can recur silently anywhere prose restates a schema.
Suggested shape
Re-derive both lists from the sources rather than hand-editing: the spec shape for claim 1, registerLayout()'s inputs for claim 2 — and consider whether the two lists belong on the guide at all, given the reference page already carries them and only one of the two copies stayed current.
Generated by Claude Code
Found while adding the canonical-key banner for #3906 (PR #5922). Not fixed there — different defect class, filed unassigned for triage.
content/docs/guide/layout.mdstates aPageHeaderPropskey list that the contract contradicts, and a registration input list thatpackages/layoutcontradicts. Two claims, both measurable, both in the same blockquote.Claim 1 — a retired key listed as declared, three live keys missing
content/docs/guide/layout.md:287:Measured against the installed
@objectstack/spec(PageHeaderProps.safeParse, values quoted from the parser's own verdict):{ title: 'Accounts', icon: 'users' }→ REJECTED,code=invalid_type path=["icon"], message: ``page:headerpropertyicon` was removed ... (ADR-0087 D2) — no renderer ever read it ...`. `icon` is a `retiredKey` tombstone on this shape, not a declared key.{ title: 'Accounts', subtitle: 'All accounts' }→ OK, output keys["title","subtitle","breadcrumb","recordChrome","showStar","showCopyId"]. The guide's list omitsrecordChrome,showStarandshowCopyId.{ title: 'Accounts', zzzNotAKey: 1 }→ REJECTEDunrecognized_keys, so the shape really is strict and the readings above mean something.The sibling page already says the right thing —
content/docs/layout/page-header.mdxliststitle / subtitle / breadcrumb / actions / recordChrome / showStar / showCopyId / aria. So two docs pages disagree, and the guide is the wrong one. An author who trusts it writesiconon a canonical node and gets a parse failure naming a key the docs told them to use.Claim 2 — the registration input list is two entries behind
Same blockquote,
content/docs/guide/layout.md:288:packages/layout/src/index.ts:121declares four:title,subtitle,icon,actions—iconandactionswere added deliberately (the registration's own comment cites objectui#3829 and objectui#3972, on renderer-read-point evidence). The word "only" is what makes this a false statement rather than an incomplete one.Why no gate caught it
Neither claim lives in a code fence, so
check-doc-component-types(type literals in code blocks) andcheck-doc-snippet-types(ts/tsxblock compilation) are both structurally blind to it.content/docs/guide/layout.mdis additionally incheck-doc-snippet-types'UNGATED_DOCSdebt list. Prose claims about a declared surface have no mechanical judge in this repo today — worth noting when sizing this, because the same drift can recur silently anywhere prose restates a schema.Suggested shape
Re-derive both lists from the sources rather than hand-editing: the spec shape for claim 1,
registerLayout()'sinputsfor claim 2 — and consider whether the two lists belong on the guide at all, given the reference page already carries them and only one of the two copies stayed current.Generated by Claude Code