Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/page-declaration-shape-gate.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
---
'@objectstack/mcp': patch
---

`CONNECT_AGENT_PAGE` is declared `: Page` (type-level only; no runtime change) so export-shape page discovery can see it. It reaches the kernel through `CONNECT_AGENT_UI_BUNDLE.pages`, but was authored as a bare `export const CONNECT_AGENT_PAGE = { … }` with per-field `as const` — the same shape `MarketplaceInstalledPage` shipped in before #11574, and invisible to the export-shape scan the canonical-envelope gates (#11255, #11480) discover their population with. A new repo-wide gate, `check:page-declaration-shape`, now closes the class: every identifier in a bundle's `pages:` array must be declared `export const X: Page =` or through `definePage()` (#11576).
11 changes: 11 additions & 0 deletions .github/workflows/lint.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -1171,6 +1171,17 @@ jobs:
- name: React pages honour the useAdapter() query and result contracts
run: pnpm check:react-page-adapter-contract

# #11576 page discovery vs ground truth: what makes something a SERVED
# page is membership in a bundle's `pages:` array (the kernel reads it in
# `registerMetadataCollections`), not its type annotation — while the
# canonical-envelope gates (#11255, #11480) discover their population by
# export shape. #11480 measured that gap on a live page. This gate makes
# the approximation exact by construction: every identifier in a `pages:`
# array must be declared `export const X: Page =` or via `definePage()`,
# so a page can never again be served-but-uncovered.
- name: Kernel-reaching pages are declared in a discoverable shape
run: pnpm check:page-declaration-shape

# #10830 form-section `name` in docs examples: the docs pages that TEACH
# the i18n-anchor convention were the one surface where nothing enforced
# it. `packages/lint`'s `translation-section-name-missing` walks app
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,6 +45,7 @@
"check:docs-image-tag": "node scripts/check-docs-image-tag.mjs --self-test && node scripts/check-docs-image-tag.mjs",
"check:docs-image-tag-sync": "node scripts/sync-docs-image-tags.mjs --self-test",
"check:react-page-adapter-contract": "node scripts/check-react-page-adapter-contract.mjs --self-test && node scripts/check-react-page-adapter-contract.mjs",
"check:page-declaration-shape": "node scripts/check-page-declaration-shape.mjs --self-test && node scripts/check-page-declaration-shape.mjs",
"check:template-version-sync": "node scripts/sync-template-versions.mjs --self-test",
"check:role-word": "node scripts/check-role-word.mjs --self-test && node scripts/check-role-word.mjs",
"check:quick-reference-counts": "node scripts/check-quick-reference-counts.mjs --self-test && node scripts/check-quick-reference-counts.mjs",
Expand Down
4 changes: 3 additions & 1 deletion packages/mcp/src/connect-ui.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,9 @@
* (`OS_MCP_SERVER_ENABLED=false`) gets no page and no nav entry.
*/

export const CONNECT_AGENT_PAGE = {
import type { Page } from '@objectstack/spec/ui';

export const CONNECT_AGENT_PAGE: Page = {
name: 'connect_agent',
label: 'Connect an Agent',
type: 'app' as const,
Expand Down
Loading
Loading