ADR-0122 The site's own harness answers for the site's surface
#Context
ADR-0119 decided that a list derives its population from the surface it reads. It was applied to tools/check-registries.js and to tools/check-roster.js. It was never applied to apps/docs/tools/check-docs.mjs, which is the largest reader of the docs surface in the repository, and every failure below is that omission.
The omission was invisible because the script died before reaching most of itself. htmlFor read a bare /components/<slug>.html with readFileSync and threw ENOENT on the first of twenty names with no such page. The docs workflow reported one stack trace. Behind it were twelve failing checks, the same shape verify-output had when it reported 8 and a trace and then 61 once it could finish.
With the crash fixed and the rest measured, on the tree this record is committed against:
- The two vocabularies have separated.
COMPONENT_LAYERSnames twenty components and none of the twenty has a directory underapps/docs/app/components. They are not absent from the site: every one of them is apermanentredirect to its replacement,status-indicatortolozenge,input-fieldandnumber-inputtotextfield,shell-headertopage-header. The site answers for all twenty by saying which component replaced each. - The route shape changed. No bare
/components/<slug>.htmlis prerendered at all.next.config.tsredirects/components/:slugto/components/:slug/examples, and the specimens are on that tab:button/examples.htmlcarries twelvewr-button,button/code.htmlcarries none. - The tab names changed.
checkSceneCountslooks forhref="/components/<slug>/evidence". The tabs arecode,usageandchangelog, plusexamples. There is noevidencetab. - The focus read asserted nothing. It required
el.closest('[class*="specimenMount"]'), and no element on the built site carries that class; the only occurrence left in the HTML is inside a CSS comment. It reported 0 focus stops and ten failures. It also spelled the selectorwr-<slug>, a guess, and the guess was wrong for two components: checkbox and radio both draw.wr-choice. - The pairing matrix has no surface.
/governance/pairing-matrixis not in the build, nothing underapps/docsreferences it, and no redirect names it.packages/eslint-plugin/receipts/pairing-matrix.jsonstill declares 194 cells. - There is no on-this-page nav.
nav[aria-label="On this page"]matches nothing on any of 400 routes. Its own check passed with 0 anchors, which is the failure mode this file's header warns about, while the sibling check reported all 160 section headings as unlisted. What the site renders instead is a per-heading anchor,a.ds__anchorwithhref="#default", beside eachsection[id]. - The analytics check asks for a third-party loader.
apps/docs/app/layout.tsxcarries nogoogletagmanagertag, and the check fails on its absence.
None of these is a site that has fallen short. Zero of twenty, zero focus stops and zero anchors are the signature of a question asked of the wrong surface, exactly as ADR-0119 described it.
#Decision
A check in the site's harness derives both its population and the route it reads from the site's own surface. Where the site has no such surface, the check retires on this record rather than failing forever.
Applied, per check:
- Population is the built route list, not
COMPONENT_LAYERSand not the keys ofpackages/tokens/component.config.json. The documented components are the slugs of the/components/<slug>/examplesroutes the build produced, which is the surface itself rather than a list describing it. The token tier and the package are answered for byverify-output.jsandcheck-roster.js, which read them directly. A docs check that reads them is asserting that the docs site ought to document the supervisor's console, which it was never rebuilt to do.
The component scene-count check retires. Its subject is gone twice over: there is no evidence tab, and no component page prints a scene count. The word evidence does not appear anywhere in apps/docs/app. The check was written while the count was being moved off the index, which the code's own comment records as becoming "a reader's gallery [that] carries no internals", and the move ended with the count on no page at all. It also cannot be repaired across the vocabulary split: the engine's scenes compose wr-status-indicator and the site documents lozenge, and no mapping between the two exists to count against.
- The route read is the tab that holds the thing being measured, which for specimens is
examples. A check that reads a bare component route is reading a redirect.
- A selector comes off the record that declares it, never from the component's name.
verify-output.jswas taught this; the harness had not caught up.
- The on-this-page checks are replaced by one that measures the anchor the site renders. Every
main section[id]must carry a link to its own id. That is the same promise to the reader, kept by the mechanism this site actually has.
- The pairing matrix route check retires. The receipt stays: it is the plugin's evidence and the plugin suite reads it. A check asserting that a route renders it is asserting a page that was removed.
- The analytics check retires. Whether the site loads a third-party tracker is a product decision, not a property of the site's correctness, and a harness that fails until one is present is a harness holding a decision hostage.
- A check that cannot find its subject reports and continues. No read assembled from a name may throw. This is the rule that made the six above visible and it is the one worth stating on its own.
#Consequences
check-docs.mjs loses four checks and gains one. Its remaining reads describe the site that exists, so a failure is a defect rather than a disagreement about which site is being measured.
The disagreement itself does not go away by being moved. Twenty components are exported by @wolf-rayet/react and documented only as redirects to their replacements, and three of them are interactive records in the token tier: input-field, number-input and navigation-item. That is ADR-0121's open table, not this record's, and this record deliberately leaves it open rather than letting a docs check keep reporting it as a docs failure.
One finding this record does not absorb, because it is a real defect rather than a misdirected question: the tabs record declares .wr-tabs, and Navigation.tsx renders a fragment carrying only wr-tabs__list, wr-tabs__tab and wr-tabs__panel. Nothing renders or styles .wr-tabs. It belongs to ADR-0121's row for tabs.
#Rejected
Give every retired component a docs page again. Twenty pages documenting components that the redesign replaced, so that a check can find them. The redirects already answer the reader's question, and better: they name the replacement.
Keep the on-this-page check and build the nav. A navigation component added to every component tab to satisfy a check, on a site whose headings already carry their own anchors. The reader gains a second way to reach what they can already reach.
Exempt the failing checks with a skip list. The failures would stop and the wrong question would remain asked.