You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#9180 step ② retired the plural /api/v1/meta/objects/:name/state/:field registration. Nothing in the tree connected that change to the prose that teaches the route, so two published sites kept teaching a retired spelling until a hand sweep found them — and the sweep that found them found a third spelling (/metadata/objects/...) that a grep for meta/objects does not match at all. Two sites for one route, found by eye, one of them invisible to the obvious search.
What exists today, and what it does not do
The route ledgers (packages/rest/src/rest-route-ledger.ts, packages/runtime/src/route-ledger.ts) are authoritative about spellings and are guarded against the server, not against prose.
scripts/check-doc-authoring.mjs walks the whole corpus (content, skills, docs, .claude) but rules on the defineX factory anti-pattern, not on wire paths.
So no gate compares a route literal in prose against a ledger row.
That PR adds packages/rest/src/meta-state-route-doc-spelling.test.ts: it reads the canonical path off the REST_ROUTE_LEDGER row for meta.getLegalNextStates and asserts both known teaching sites contain it (presence, not absence — "no doc contains the plural" passes on a page that stopped documenting the route at all). Reverse-verified: mutating the docs page back to the plural reddens it by name; restoring greens it.
It is deliberately narrow, and its limit is the point of this card: it is a curated list of two files. A list of the files that already exist can never contain the one added tomorrow — which is exactly how these two sites came to exist. It also covers one route out of the hundreds the ledgers carry.
The shape a real detector would have
The repo's own convention for whole-corpus scans is a root-level gate script (check-doc-authoring.mjs is the model), not a package test — a package test would need content/docs/** and skills/** as declared turbo inputs, invalidating that package's cache on every docs edit.
Sketch, for whoever picks this up:
walk the published prose corpora (content/docs/** minus releases/, plus skills/**);
extract wire-path literals;
for each, ask whether some ledger row declares that exact path, and fail on a literal that matches a ledger row's shape while differing from its spelling;
assert a floor on the number of literals found, so an evaporated corpus cannot read as a clean one (the #4932 discipline that gate already documents).
⚠️ Two constraints any implementation must respect, both load-bearing:
The plural is not universally dead. The legacy if-chain branch in the runtime's /meta domain still matches both objects and object, so /meta/objects/:name/state/:field is refused by a REST-fronted deployment and still answered wherever dispatch() fronts the request. That is deliberate (maintainer re-weigh of the [Ruling] The /meta type segment is ALWAYS singular — retire every plural spelling, no exception, in three steps #9180 ruling, 2026-08-17 item 3) and pinned by the meta-state-plural-tolerance suite. A detector that treats every plural as a defect would be wrong, and "narrow the tolerance to make the gate simple" is the maintainer's call, not the implementer's.
It is not the META_URL_TO_SINGULAR fold, whose retirement was deferred separately. The ledger note calls conflating the two "the specific error to avoid".
Sizing note: this is a new gate plus its --self-test plus lint.yml wiring, and its scope (which corpora it owns) is a policy decision with history in this repo — every expansion of check-doc-authoring.mjs's roots was its own card. Worth triaging as such rather than riding along on a docs fix.
Part of the #9180 family in spirit; not blocked by anything.
Measured while implementing #10178. Filed unassigned; observation, not a claim on anyone's time.
What #10178 measured
#9180 step ② retired the plural
/api/v1/meta/objects/:name/state/:fieldregistration. Nothing in the tree connected that change to the prose that teaches the route, so two published sites kept teaching a retired spelling until a hand sweep found them — and the sweep that found them found a third spelling (/metadata/objects/...) that a grep formeta/objectsdoes not match at all. Two sites for one route, found by eye, one of them invisible to the obvious search.What exists today, and what it does not do
packages/rest/src/rest-route-ledger.ts,packages/runtime/src/route-ledger.ts) are authoritative about spellings and are guarded against the server, not against prose.scripts/docs-audit/affected-docs.mjshas arouteanchor kind, but it is a drift alert scoped tocontent/docs/**/*.mdx— it tells you a page may be affected, it never asserts a page is correct, andskills/**is outside its scope entirely. Its own reach is already known to be partial ([finding] docs-drift's route bridge can reach only 45 of the 221 client-bound ledger routes — 176 have no registrar tail at all, and the variable-path recall half of #9503 is a small slice of it #9572: 45 of 221 client-bound rows carry a registrar tail).scripts/check-doc-authoring.mjswalks the whole corpus (content,skills,docs,.claude) but rules on thedefineXfactory anti-pattern, not on wire paths.So no gate compares a route literal in prose against a ledger row.
What #10178 added, and why it is not the answer
That PR adds
packages/rest/src/meta-state-route-doc-spelling.test.ts: it reads the canonical path off theREST_ROUTE_LEDGERrow formeta.getLegalNextStatesand asserts both known teaching sites contain it (presence, not absence — "no doc contains the plural" passes on a page that stopped documenting the route at all). Reverse-verified: mutating the docs page back to the plural reddens it by name; restoring greens it.It is deliberately narrow, and its limit is the point of this card: it is a curated list of two files. A list of the files that already exist can never contain the one added tomorrow — which is exactly how these two sites came to exist. It also covers one route out of the hundreds the ledgers carry.
The shape a real detector would have
The repo's own convention for whole-corpus scans is a root-level gate script (
check-doc-authoring.mjsis the model), not a package test — a package test would needcontent/docs/**andskills/**as declared turbo inputs, invalidating that package's cache on every docs edit.Sketch, for whoever picks this up:
content/docs/**minusreleases/, plusskills/**);#4932discipline that gate already documents)./metadomain still matches bothobjectsandobject, so/meta/objects/:name/state/:fieldis refused by a REST-fronted deployment and still answered whereverdispatch()fronts the request. That is deliberate (maintainer re-weigh of the [Ruling] The/metatype segment is ALWAYS singular — retire every plural spelling, no exception, in three steps #9180 ruling, 2026-08-17 item 3) and pinned by themeta-state-plural-tolerancesuite. A detector that treats every plural as a defect would be wrong, and "narrow the tolerance to make the gate simple" is the maintainer's call, not the implementer's.META_URL_TO_SINGULARfold, whose retirement was deferred separately. The ledger note calls conflating the two "the specific error to avoid".Sizing note: this is a new gate plus its
--self-testplus lint.yml wiring, and its scope (which corpora it owns) is a policy decision with history in this repo — every expansion ofcheck-doc-authoring.mjs's roots was its own card. Worth triaging as such rather than riding along on a docs fix.Part of the #9180 family in spirit; not blocked by anything.