Restart-when: a fourth page-carrying contributor is registered in the CONTRIBUTORS list of packages/cli/scripts/check-app-nav-i18n.mjs, or a pages.* entry changes in packages/platform-objects/src/apps/translations/en.ts, or a listed bundle gains a conditional page
Observation filed while implementing #8764 (the pages.* default-locale content-parity assertion in packages/cli/scripts/check-app-nav-i18n.mjs). Deliberately out of that card's scope and stated there as a non-claim. Filed unassigned for triage.
What #8764 closed, and what it did not
#8764 added a forward assertion: for every pages.NAME entry the default-locale bundle declares, the values must match the page metadata the composition actually carries, and an entry naming a page the composition does not contain fails as an orphan.
The reverse direction is not asserted: a page that IS in the composition but has NO entry in packages/platform-objects/src/apps/translations/en.ts is not reported by anything. So a new page shipped tomorrow by @objectstack/cloud-connection or @objectstack/mcp — the two packages that already contribute the existing three — reaches users as whatever English literal its author typed, in all four locales, under a fully green build. There is no key for a translator to fill because nobody is told one is missing.
Why it was left out rather than added
The gate states a deliberate non-claim about reverse assertions for nav: a conditionally-contributed entry is indistinguishable from a dead key when all you have is one runtime composition, so demanding a bundle entry for everything present would delete the labels of entries this composition merely happens not to merge.
That reasoning transfers to pages only partly, which is exactly why this deserves its own decision rather than a quiet extension:
- The three page-carrying bundles are registered unconditionally in that gate's
CONTRIBUTORS list as static manifest exports, so for those, presence is deterministic and a coverage demand would be sound. - But
MCPServerPlugin registers CONNECT_AGENT_UI_BUNDLE in the real runtime gated on OS_MCP_SERVER_ENABLED, and the marketplace pages ship with their capability plugins (cloud ADR-0009: no plugin, no entry). A future page could easily be genuinely conditional, and then the same indistinguishability applies.
So the honest options differ in cost and in blast radius, and the choice is triage's:
- Demand a bundle entry only for pages carried by the manifests this gate lists explicitly — narrow, sound today, needs a rule for what happens when a listed bundle gains a conditional page.
- Treat it the way Setup nav's reverse direction is treated — a hand-kept list decided per page by a human, alongside
setup-nav-dead-key-tombstone.test.ts. - Leave it, and accept that page-header copy is covered for drift but not for arrival.
Severity
No live defect: the three pages that exist today all have entries, and #8764 now compares them. This is an unexercised hole about pages that do not exist yet — the same "not looked at here" shape the original nav gate was filed for, one surface over.
Backlinks: #8764, #8721.
Generated by Claude Code
Generated by Claude Code
Restart-when: a fourth page-carrying contributor is registered in the CONTRIBUTORS list of packages/cli/scripts/check-app-nav-i18n.mjs, or a pages.* entry changes in packages/platform-objects/src/apps/translations/en.ts, or a listed bundle gains a conditional page
Observation filed while implementing #8764 (the
pages.*default-locale content-parity assertion inpackages/cli/scripts/check-app-nav-i18n.mjs). Deliberately out of that card's scope and stated there as a non-claim. Filed unassigned for triage.What #8764 closed, and what it did not
#8764 added a forward assertion: for every
pages.NAMEentry the default-locale bundle declares, the values must match the page metadata the composition actually carries, and an entry naming a page the composition does not contain fails as an orphan.The reverse direction is not asserted: a page that IS in the composition but has NO entry in
packages/platform-objects/src/apps/translations/en.tsis not reported by anything. So a new page shipped tomorrow by@objectstack/cloud-connectionor@objectstack/mcp— the two packages that already contribute the existing three — reaches users as whatever English literal its author typed, in all four locales, under a fully green build. There is no key for a translator to fill because nobody is told one is missing.Why it was left out rather than added
The gate states a deliberate non-claim about reverse assertions for nav: a conditionally-contributed entry is indistinguishable from a dead key when all you have is one runtime composition, so demanding a bundle entry for everything present would delete the labels of entries this composition merely happens not to merge.
That reasoning transfers to pages only partly, which is exactly why this deserves its own decision rather than a quiet extension:
CONTRIBUTORSlist as static manifest exports, so for those, presence is deterministic and a coverage demand would be sound.MCPServerPluginregistersCONNECT_AGENT_UI_BUNDLEin the real runtime gated onOS_MCP_SERVER_ENABLED, and the marketplace pages ship with their capability plugins (cloud ADR-0009: no plugin, no entry). A future page could easily be genuinely conditional, and then the same indistinguishability applies.So the honest options differ in cost and in blast radius, and the choice is triage's:
setup-nav-dead-key-tombstone.test.ts.Severity
No live defect: the three pages that exist today all have entries, and #8764 now compares them. This is an unexercised hole about pages that do not exist yet — the same "not looked at here" shape the original nav gate was filed for, one surface over.
Backlinks: #8764, #8721.
Generated by Claude Code
Generated by Claude Code