The door read `name === id` as "never named". The New Project dialog derives
the id from the name, so `blog`, `my-app` or a repo folder name gave the same
string for both, and the reference said `Project` where the base showed the
name. Only the minted shape `proj_<hex>` is a non-name now; the test pins both
directions.
Also: the question flag on the reference is `data-opens-question`, so an
unqualified `[data-quiz-id]` selector still matches the quiz card alone; the
single-raiser scan reads code, not comments, and says what it cannot see; the
inventory scans the first-party shell scripts too (`theme.js` raises
`ouro:theme-changed`); DESIGN no longer claims the reference names the Project
on the routed message, nor that the inventory lists every control.
- The inventory scanner ended a `<button` tag at the first `>`, including one
inside a templated attribute (`${rows.length >= MAX ? 'disabled' : ''}`), and
listed `= MAX_AVAILABLE_SUBAGENTS ? … }>Add subagent` as control text. The
attribute part now steps over `${…}`; a real-shape regression pins it and
fails on the old pattern.
- DESIGN said the reference "says to a screen reader what it says to the eye".
It does not, on purpose: the pixels are glyph, name and arrow, the accessible
name is the sentence `Open project <name>`. The rule now says that.
- Comments and docstrings that still described `in project ↗` and an
`Open Project` control name the Project reference instead.
Design drift here happens at the level of owner intents, and the siblings of a
new control are never in its diff. `docs/inventories/UI_CONTROL_TEXT_INVENTORY.md`
puts them there: every `<button>` literal with fixed text, every created button
with a literal `textContent`, the fixed accessible name of icon-only buttons,
and every `ouro:*` CustomEvent with the modules that raise it. It is sorted by
text, so a new `Retry` lands in the same hunk as the `Retry` rows that already
exist, with their classes and files beside it.
Staleness is its only red (byte identity in tests/test_generated_inventories.py,
like the other three). Run-time text is counted, never listed or guessed; the
scan reads countable source facts and never judges what a control means.