Skip to content

refactor(layout)!: retire the navigation-renderer and responsive-grid node type keys; navigation is app metadata, the breakpoint grid is grid (objectui#11441) - #11460

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-11441-retire-nav-responsive-grid
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-11441-retire-nav-responsive-grid

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #11441

Clause-②: yes

Part of #10859: this card runs as one more batch of that family, on the same ratchet. It executes the maintainer's ruling on objectui#11441, record 5950208338 (batch 268 item 5, letters B / B, 「同意」), under the seat's claim 5950898710. Dispatched dev of domain:ui seat 1, session https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37.

What changes

  • packages/layout/src/index.ts: the responsive-grid and navigation-renderer registrations (each with its layout: twin) become tombstone docblocks. They describe the retired calls and do not quote them, because the registration readers take a quoted call in a comment for a live one. The two imports that only fed the registrations go; export * keeps both components public.
  • The components stay exported. NavigationRenderer is what app-shell's UnifiedSidebar and this package's AppSchemaRenderer mount. ResponsiveGrid had no in-repo consumer except the retired registration, so it is now a React-only export. It stays because the ruling keeps objectui#7580's vocabulary half: BreakpointColumnMap stays declared in ResponsiveGrid.tsx, unchanged, as the type of its columns prop. ⛔ BreakpointColumnMap is not removed.
  • known-schema-types.ts is regenerated by node scripts/regenerate-known-schema-types.mjs. Four entries leave: navigation-renderer, responsive-grid, layout:navigation-renderer, layout:responsive-grid.
  • The ratchet (registered-types-validate-ratchet-10859.test.ts): REFUSED_AT_TYPE 20 → 18 and NAMESPACED_REFUSED_AT_TYPE 374 → 372. Both namespaced twins were refused at type on both faces (measured), so the namespaced pin moves by 2. A new UNREGISTERED_11441 map and its row; STILL_REFUSED_10859 loses both keys and its set-equality row holds; the docblock's projection now reads 8 after phase 2d and 0 after objectui#11440.
  • Pins whose subject left. navigation-renderer-items-declaration.test.tsx is deleted: its objectui#3972 / objectui#3987 rows read the declaration that is gone. navigation-responsive-grid-retired-11441.test.tsx replaces it: the source read and the live registry both lack every spelling (lit control app-schema-renderer, both spellings), a node of either key renders the OBJUI-001 panel (render control layout:page:card), NavigationRenderer is still exported, and ResponsiveGrid still resolves a breakpoint map. In the schema-catalog file, the objectui#3972 / objectui#3987 manifest describes go, a retirement pin replaces them (lit control grid), and the objectui#3900 containment control moves to app-schema-renderer.
  • Lit controls that used responsive-grid move: app-shell-not-a-component-key to layout:page:card; page-header-authorable-keys and the side-effects bundle probe to app-schema-renderer; the layout containment census to its two remaining registrations. The sidebar-nav doc pin learns the number word two. Scope notes that said navigation-renderer takes an icon name now say NavigationRenderer, the component that still does.
  • Teaching. content/docs/guide/layout.md: the registered-key sentence (two keys) and the paragraph on a navigation tree that must come from JSON, which now points at the app document's navigation items drawn by the shell. The layout README, the docs-site registrar docblock, and the @object-ui/types comments (mobile.ts, complex.ts, index.ts, two test comments) that named the responsive-grid registration as the ground for the re-homed breakpoint vocabulary: they now name grid's breakpoint columns, keyed by BreakpointName, and ResponsiveGrid's prop.
  • Changesets. @object-ui/layout minor and @object-ui/cli minor, each with the BREAKING (authoring) banner and migration lines. Dated notes on the three pending entries that named either key as live: 10859-retire-page-header-layout, 7580-responsive-vocabulary-rehome (the ruling updates its item 2), 9910-children-slot-declare-and-pin; frontmatter md5 unchanged on all three. No console entry: apps/console has no stub for either key (grep 0). @object-ui/types changed comments only and carries no entry.

Premise gate, re-measured

  • objectui at ad1785c1d (main with phase 2c): outside CHANGELOGs, every hit for either key is the registration, the generated list, a test, a comment or prose. 0 producers in non-test source, examples/**, the catalog, content/docs and skills/**; 0 runtime emission.
  • objectstack origin/main 3b4efa74: git grep -E "navigation-renderer|responsive-grid" exit 1 (0 hits). Control in the same command shape: page-header answers 23 files. The NavigationRenderer / ResponsiveGrid hits there name the React components in prose.
  • One teaching site the card's "0 teaching sites" did not count: the layout guide advised "navigation-renderer when the tree has to come from metadata" (prose, no node authored). It is corrected here to the ruling's home for navigation. Not a producer, so no fork.

Migration lines, measured on both faces

safeValidateSchema (tolerant, what objectui validate runs) and StrictAnyComponentSchema (strict), at this head:

document tolerant strict
responsive-grid with columns: { xs: 1, md: 2 }, and layout:responsive-grid refused at type refused at type
navigation-renderer with items: [], and layout:navigation-renderer refused at type refused at type
grid with columns: { xs: 1, md: 2 }, gap: 4 and one child pass pass
grid with columns: { xs: 1, xxl: 6 } (control) unrecognized_keys at columns (xxl) same
app with name and a one-entry navigation array pass pass
app with navigation as an object (control) invalid_type at navigation same
app with name, basePath and navigation: [] pass unrecognized_keys (basePath)
app-schema-renderer with a schema object refused at type (objectui#11440 arms it) same

Through the real SchemaRenderer (a temporary probe, deleted): grid with { xs: 1, md: 2 } and gap: 4 renders grid grid-cols-1 md:grid-cols-2 gap-4 and draws its child; responsive-grid renders the OBJUI-001 panel, which the new test now pins. So the layout changeset names grid with columns / gap, and the app document's navigation; it says the strict face refuses basePath on the app document as an unrecognized key; and it does not recommend the app-schema-renderer node, which objectui validate refuses at type today.

Verification, all at head 7f4f8ab64

  • Union (through os-verify-lock): the ratchet, check-known-types, known-schema-types-derivation-5115, check-doc-component-types.test, unit-registry-absence-collision, registry-bare-name-collisions, component-registrations, side-effects-declaration-consistency, site-playground-layout-registration-3904, the schema-catalog pageheader-with-actions, the two @object-ui/types test files, and all of packages/layout/: Test Files 46 passed (46), Tests 665 passed (665), VERDICT command-exit 0. A second run over the source-reading pins (node-slot-registered-arms-8499, both container-declaration census / ratchet files, check-prompt-component-keys, check-sdui-registration-pins.test, registry-assertion-ratchet-8316, three @object-ui/types files naming app-schema-renderer, grid-breakpoint-columns-7097): Test Files 10 passed (10), Tests 925 passed (925).
  • type-check after closure builds, each echoing its script: @object-ui/types, @object-ui/layout, @object-ui/cli, @object-ui/example-schema-catalog, and type-check:scripts, all Done / exit 0. Every changed test file is in its program (--listFilesOnly).
  • Gates, exit 0: check:doc-types (887 registered + 290 exempted of 1177 sites), check:doc-snippets (after its --build-filter turbo build, 35/35 tasks), check:doc-examples, check:doc-example-ids, check:doc-fences, regenerate-catalog-index.py --check, regenerate-known-schema-types.mjs --check, check:registry-bare-names, markdown-test-inputs.mjs --audit, check-doc-links.mjs, check-changeset-presence.mjs (17 source files of 3 released packages, 2 changesets), check:changeset-claims (report-only; the 23 pending entries it lists were read, none falsified), changeset:check, check:pending-changeset-literals, check:control-bytes, check:new-line-citations (0 new), check:prompt-keys, check:installed-pin-claims, check:spec-symbols, check:test-path-roots, check:handler-key-reads, check:component-surface-parity, check:side-effects-array, check:unreferenced-sources, check:doc-example-readers, check:readme-exports, check:skills-paths, and check:sdui-registration-pins after a console build (14 of 14 derived registrations present; the two retired keys left the derived set).
  • ESLint, narrowed: eslint --no-inline-config --format json over the 20 changed ts/tsx files that exist, each compared with its base blob through --stdin: per-file error and warning counts equal the base in every file (2 pre-existing no-restricted-imports errors in @object-ui/types, visible only without inline config, identical at base). Population: the root eslint.config.js is the only config, read by the package lint scripts (eslint .; cli eslint src). It sets no projectService or parserOptions.project, so type-aware linting is off and this diff cannot move a verdict on an untouched file. Full pnpm lint is CI's.
  • Governed check: check-governed-queue-guard --test over the 28 paths answers NOT GOVERNED. Control-byte self-scan over the 27 changed files: 0 hits.

Reverse verification and ablation, predicted first

  • Base leg: packages/layout/src/index.ts and known-schema-types.ts checked out at ad1785c1d, new tests kept. Predicted 11 red: 4 ratchet rows, 4 in the new layout file, 2 in the schema-catalog retirement pin, 1 in the sidebar-nav doc pin. Got Tests 11 failed | 128 passed (139), exactly those, including "refuses 20 registered bare key(s) at type; the pin is 18" and "refuses 374 registered namespaced key(s) at type; the pin is 372". Restored by a trap: both blobs equal HEAD, git diff HEAD 0 lines.
  • Ablation through objectstack's scripts/ablation-replace.mjs (WRAP mode), restoring ONE registration, responsive-grid, with its import: anchor 1 → 0, blob e4f4ea8ea800 → 90f86f86b05b, and the on-disk count of the register call is 1. Leg 1 (source only), predicted: derivation-5115 red plus 5 rows. Got 7 failed: the two derivation rows ("omits no registered type", "matches … byte for byte"), three in the new layout file, the schema-catalog responsive-grid row and the sidebar-nav doc row. Leg 2 (list regenerated under the ablation), predicted 9: got 9, with "refuses 19 … the pin is 18" naming responsive-grid and "refuses 373 … the pin is 372", the 11441 row and the set-equality row, plus the same five; derivation-5115 green. Restored: the tool proved index.ts blob equals HEAD with git diff HEAD empty, and my trap proved the regenerated list's blob equals HEAD.

Acceptance notes (out of scope, not filed)

  • skills/objectui/rules/protocol.md (governed) still says BreakpointColumnMap in @object-ui/layout (responsive-grid) spells the same six. The claim about six keys stays true; the parenthetical now names a retired key. Editing it would make this PR governed, so it is left for a separate governed one-line change, named in the dev report.
  • scripts/__tests__/component-registrations.test.ts keeps responsive-grid and page-header as synthetic fixture strings for the registration reader. They are not registry claims, and phase 2c left page-header the same way.

Serial

  • objectui#10859 phase 2d edits the same ratchet test. Whichever lands second merges main and re-pins; with its ten sidebar-* retirements on top of this the bare pin goes 18 → 8.
  • main moved to 4a1adb76e (objectui#11456, i18n) after this branch merged ad1785c1d. No file overlaps this diff, and the queue rebuilds on current main.

Generated by Claude Code

… node type keys (objectui#11441)

The maintainer's ruling on objectui#11441 (record 5950208338, letters B / B),
executed as one more objectui#10859 batch:

- packages/layout/src/index.ts: both registrations become tombstone
  docblocks (described, not quoted). NavigationRenderer and ResponsiveGrid
  stay exports; BreakpointColumnMap stays declared (the ruling keeps the
  objectui#7580 vocabulary half).
- known-schema-types.ts regenerated: the two bare keys and their layout:
  twins leave. The ratchet goes 20 -> 18 (bare) and 374 -> 372
  (namespaced), with a row for this batch and the named remainder updated.
- The navigation-renderer declaration pins (objectui#3972 / #3987) end with
  the declaration; a retirement pin replaces them, and the #3900
  containment control moves to app-schema-renderer.
- Teaching corrected: the layout guide, the layout README, the docs-site
  registrar docblock, and comments in @object-ui/types that named
  responsive-grid as the ground for the re-homed breakpoint vocabulary.
- Changesets: layout and cli minor with the BREAKING (authoring) banner;
  dated notes on three pending entries that named either key as live.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 23 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/10756-html-tier-code-element.md

  • names packages/cli/src/utils/known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    • @object-ui/components — code joins the TAGS loop of html-elements.tsx: registered ui:code, sanitised like its siblings, declaring className and the children slot. An html author's ANGLE-BRACKETS(code) now renders a real code element with its text. - @object-ui/fields — BREAKING (authoring): the bare code key no longer resolves to the code-editor widget. code joins FIELD_TYPES_SKIP_FALLBACK, so the widget is registered field:code only. A node authored as bare { "type": "code", "value": … } now renders the html tier's code element (it draws children, not value); in a registry without @object-ui/components the bare key resolves to nothing. Migration: { "type": "code" } becomes { "type": "field:code" }. Form fields of type code resolve through the field: namespace and render the same editor as before. Released as minor under objectui's version policy; a breaking change never declares major. - @object-ui/core — code joins HTML_TIER_INTRINSICS, so getPublicConfigs() projects it stamped tier: 'html' and the regenerated sdui.manifest.json grows by one entry (the html tier declares 48 tags where objectui#10735 declared 47); div and kbd stay undeclared. - @object-ui/types — HtmlElementSchema (zod and TS) names code, keeping the JSON-surface declaration equal to the registration, as the objectui#8499 pin requires — so AnyComponentSchema (and objectui validate) now accepts { "type": "code" }, which it refused before. - @object-ui/cli — packages/cli/src/utils/known-schema-types.ts regenerates from the registrations and gains ui:code, so objectui validate and objectui check recognise it as a known schema type (the objectui#9533 and objectui#6416 precedent).

.changeset/10859-known-types-retired-keys.md

  • names packages/cli/src/utils/known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    BREAKING (authoring): KNOWN_SCHEMA_TYPES (packages/cli/src/utils/known-schema-types.ts, regenerated from the registration calls) no longer lists the 28 bare field-widget fallbacks retired in @object-ui/fields, nor tree / view:tree (@object-ui/plugin-tree) or view / plugin-view:view (@object-ui/plugin-view). objectui check now reports a root document of one of those types as an unknown type, and objectui validate keeps refusing it at type, as it already did.

.changeset/10867-app-wizard-saves-spec-app.md

  • names spec-derived-unions.test.ts → packages/types/src/__tests__/spec-derived-unions.test.ts — edited by this change

    • A separator carries only type, id and order. @objectstack/spec's separator branch declares exactly those keys, and its AppSchema refuses anything else. NavigationItem required a label on every item, so the wizard's "Add separator" wrote { id, type: 'separator', label: '' }, and the console's create-app and edit-app saves were refused with 422 INVALID_METADATA (unrecognized_keys ['label'] at navigation.N). NavigationItem is now a union of two arms, discriminated by type. NavigationEntryItem holds every other nav type and keeps its required label. NavigationSeparatorItem admits type, id and order, and every other entry key is ?: never on it. Both arms are exported. Reading an entry-only key off an unnarrowed item still compiles, but its type now includes undefined (a label is string | undefined; objectui#11299, in the same release, makes it the spec's I18nLabel or undefined, see .changeset/11299-types-nav-label-locale-map.md), so passing it where a string is required does not. Narrow on item.type === 'separator' before relying on label. menuItemToNavigationItem maps a legacy separator to { id, type: 'separator' } and drops its label. spec-derived-unions.test.ts no longer pins the separator label as a blocker. It asserts, at both spec tiers, that the separator arm admits the spec separator's keys and no others. - @object-ui/plugin-designer: the wizard and NavigationDesigner write a separator as { id, type }. NavigationDesigner no longer writes a label onto a new separator, and its label, icon and visibility patchers skip one. - @object-ui/layout narrows on the separator arm; nothing it renders changes. resolveNavItemLabel answers '' for every separator. A stored separator carrying a non-empty label, which menuItemToNavigationItem produced before this change, used to resolve to that label. No renderer asks it for a separator's label. The mobile bottom nav's leaf list, which already skipped separators, is now typed as entries. - @object-ui/app-shell narrows the same way; nothing it renders changes. useNavPins registers a favorite only for an entry and leaves a separator as it is, and the Studio sidebar's navigation walk passes a separator through unchanged. - @object-ui/plugin-designer: EditAppPage keeps the stored branding. The wizard maintains the logo, primary colour and favicon, and its branding replaced the stored block, so a stored accentColor was dropped on every edit. The console reads that key. The save now keeps every stored branding key the spec's AppBrandingSchema declares, read from that schema. The wizard's values win for the keys it maintains. A stored key the spec does not declare is still left out. - The wizard's Layout control is removed, with AppWizardDraft.layout. The spec declares no app layout, no console surface reads one, and since objectui#10842 the save wrote none. The control persisted nothing. EditAppPage no longer reads a stored layout into the draft. The Basic Info step's description now reads "Name, title, and icon". - @object-ui/i18n: the four appDesigner layout keys (layout, layoutSidebar, layoutHeader and layoutEmpty) are removed from all ten packs, and appDesigner.stepBasicDesc no longer names a layout.

.changeset/5213-widget-ts-retired-spec-anchor-history.md

  • names packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts → packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts — edited by this change

    A per-key description of a schema that no longer exists is the ADR-0033 failure: an AI author reads a published docblock as present-tense fact and builds on it. The enumeration is dropped rather than re-dated, and the blocks now say what is true today — the bare names are owned by NOBODY, RuntimeWidgetManifest is objectui's only widget-registration contract, and the Runtime prefix is kept BY CHOICE (objectstack#4988's precedent: a freed word is not a reason to spend a second breaking rename taking it back; the unlock is recorded, not taken, in objectui#4164). The inline collision that made the WidgetSource rename urgent is kept, in the past tense, because it is the reason the prefix exists. Both blocks now point at the live assertion instead of restating it: the "the spec no longer owns" rows in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts, which are what goes red if the spec ever re-publishes either name.

.changeset/6051-gantt-flat-config-declared-keys.md

  • names packages/types/src/index.ts → packages/types/src/index.ts — edited by this change

    GanttConfig itself gains nine members and is a published type, exported by name from packages/types/src/index.ts: lockField, objectField, summaryExtent, defaultCollapsedDepth, borderColorField, dependencyTypes, timeZone, exportFileName, interactions. The entry file's diff is empty only because the export list already named the type — the widening happened at the declaration.

.changeset/6416-plugin-report-namespace.md

  • names packages/cli/src/utils/known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    packages/cli/src/utils/known-schema-types.ts is regenerated from the registrations, dropping report:report, report:report-viewer and report:spec-report.

.changeset/6687-chatbot-surface-authorable.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    Measured on both declaration faces before the fix, each with a control that had to hit: schema.surface appeared 0 times in renderer.tsx against schema.placeholder at 3 (one per registration) and schema.processVisibility at 1; and ChatbotSchema (packages/types/src/complex.ts) declared 34 keys, not this one. Two faces agreeing is what made the zero a reading rather than a bad query.

.changeset/6872-app-shell-branding-title-jsdoc.md

  • names content/docs/guide/layout.md → content/docs/guide/layout.md — edited by this change

    Correct the AppShellBranding.title doc comment. It read "Page title suffix (sets document.title)" while useAppShellBranding assigns document.title = title wholesale — nothing is appended; the caller composes the whole string (the console passes "App label — Product name"). That comment ships in dist/index.d.ts and is the only description a consumer sees on editor hover, so a reader who followed it passed a suffix-only fragment and got a truncated title with no error. The comment now carries the same wording as content/docs/layout/app-shell.mdx, and agrees with the AppShellProps tables in the package README and content/docs/guide/layout.md. No runtime behaviour changes; the wholesale assignment and the four-surface agreement are now pinned by tests.

.changeset/6939-kanban-column-cards.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    Breaking, deliberately. KanbanColumn declared its card list as items in complex.ts and in the zod mirror complex.zod.ts. Every board reads cards. Measured on origin/main 78a3cc238: KanbanImpl.tsx reads .cards on 12 lines, KanbanEnhanced.tsx on 8, and bucketCardsIntoColumns twice more as col.cards || []; .items had zero read sites in either board (a same-shaped .title control on the same two files returns 8 and 3, so those zeros are readings and not a mis-shaped probe). Both catalog entries, the plugin docs and content/docs/api/schema-reference.md all author cards.

.changeset/7122-spec-17-3-0-parity-reconciliation.md

  • names known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    user:profile is retired across all three sites. 17.3.0 dropped it from PageComponentType (measured: the enum went 34 → 32 options, lost set exactly ['user:profile', 'element:form'], gained set empty). objectui went on knowing it in three places, so all three moved together: the Studio palette exclusion ledger, PROTOCOL_COMPONENTS in renderers/placeholders.tsx, and the regenerated known-schema-types.ts the CLI checks schemas against. Nothing user-reachable went with it — neither type had a renderer, user:profile had only the dashed "Component Placeholder" scaffold, and the app shell's own profile affordance is a React slot, never this block type. A page schema still naming it now draws the loud "Unknown component type" panel rather than a silent grey box, which is this repo's standing treatment for a type outside the supported surface.

.changeset/7295-chat-message-avatar-keys.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    packages/plugin-chatbot/src/index.tsx:173–178 reads message.avatar || userAvatarUrl and message.avatarFallback || userAvatarFallback (and the assistant twins), the authoring-to-runtime seam spreads every unlisted key through (chatMessageAdapter.ts, ...passthrough), and the SDUI renderer feeds the authored messages[] straight in — a per-message avatar override renders, is documented, and no authoring-facing type declared it. ChatMessage in packages/types/src/complex.ts has no index signature (objectui#5155, deliberately — none is added here), so an author annotating ChatbotSchema.messages was told a value that renders is an error (TS2353); the zod mirror ChatMessageSchema is a plain strip-mode z.object, so the value parsed green and was silently DROPPED from the parsed output.

.changeset/7655-chatbot-registration-authoring-faces.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    New published symbol: ChatbotSharedKey, the string-literal union of the twenty keys all three registrations read. It is exported from complex.ts because an exported interface may not extend a Pick over a private name (TS4022), so it is emitted into dist/complex.d.ts and is reachable through the published @object-ui/types/complex subpath (it is not re-exported from the package entry). It is a census, not an authoring face.

.changeset/7703-chatbot-dark-keys-retired.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    Each member goes to ?: never on packages/types/src/complex.ts and to retirementTombstone(...) on packages/types/src/zod/complex.zod.ts — both halves, in lockstep, the convention MarkdownSchema.sanitize (objectui#6972), TimelineSchema.timeScale (objectui#6355) and ObjectViewSchema.viewTabBar (objectui#7779) already carry. Each refusal names the key, says why it is retired, and points at what to write instead; one string feeds both the parse-time message and the .describe() metadata, so the two cannot drift.

  • names mobile.ts → packages/types/src/mobile.ts — edited by this change

    All six have a Zod arm, and that is what decides the route here. BaseSchema is .passthrough() on the Zod side and carries a [key: string]: any index signature on the TS side, so an UNDECLARED key is not refused — it is KEPT. Deleting the members would hand the authored spelling exactly the silent no-op this card exists to close, on both faces at once. This package's retire-vs-remove discriminator (objectui#5941 / feat(types,mobile)!: retire the MobileComponentConfig published type #7526, in its amended form, 5f8190c8c) leaves that structural hazard to the carrier: where there is no mirror there is "no silent-strip hazard for prong 2 to guard" (mobile.ts). Here there is a mirror to host the refusal, and prong 1 holds by the letter for four of the six. The "deleted" row is pinned live as a control in packages/types/src/__tests__/chatbot-dark-keys-retired-7703.test.ts, so the contrast cannot rot into prose.

.changeset/7704-schema-registry-chatbot-keys.md

  • names packages/cli/src/utils/known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    packages/plugin-chatbot/src/renderer.tsx registers three components — chatbot, chatbot-enhanced and chatbot-floating — and SchemaRegistry mapped one of them. Since ComponentType = keyof SchemaRegistry is the published union, a consumer discriminating on it was told two registered keys do not exist: an author narrowing a node by ComponentType, or writing a RecordANGLE-BRACKETS(ComponentType, …) table, had no arm for either. The asymmetry that showed which half was wrong is that packages/cli/src/utils/known-schema-types.ts keeps its own parallel list containing both keys, precisely because this map did not.

.changeset/7926-page-node-refuses-actions.md

  • names content/docs/guide/layout.md → content/docs/guide/layout.md — edited by this change

    Scope. One key, by name; the node is NOT strict. A census over this tree read 91 authored page-tagged objects with a blind-spot reading of 8 unreadable sites, and found only actions (3 sites, all in content/docs/guide/layout.md) and breadcrumbs (1 site, its own question, untouched) surviving passthrough on a real page node — every other undeclared key belongs to a different declaration that merely spells type: 'page'. PageNodeSchema still passes unknown renderer props through.

.changeset/8415-filter-builder-condition-id.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    Breaking for authored metadata: a filter-builder CONDITION must now declare id (objectui#8415). It is declared on both published faces — the TypeScript interface FilterBuilderCondition in complex.ts and the Zod mirror FilterBuilderConditionSchema in zod/complex.zod.ts — so a key the renderer has always required is finally validated instead of silently discarded.

.changeset/8802-8257-8008-kanban-gantt-family-retirement.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    What each retirement was, measured. Three of the four were registration-only: no schema face in @object-ui/types ever declared kanban-ui, kanban-enhanced or gantt as a component node type, so unregistering is the whole retirement. The bare kanban key was the exception — it had a declared arm on both faces (KanbanSchema in complex.ts and its Zod mirror), and a plain deletion there would have been the objectui#7664 failure: BaseSchema is .passthrough(), so a document naming a dropped key validates green and renders nothing. It therefore retires as a named refusal: the Zod union keeps an arm claiming the literal and answers a { "type": "kanban" } document with a message naming object-kanban as the remedy, while the TypeScript half is the absence of the arm from ComplexSchema and of the key from SchemaRegistry, so tsc refuses it at the authoring site.

  • names known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    ⚠️ objectui check will NOT flag either namespaced spelling. The CLI's known-schema-types.ts is generated from the repository's real registration calls, and the placeholder registration is a real one — so view:kanban and view:gantt are still on that list and still validate green, while the node renders a placeholder rather than a board. The bare kanban / gantt entries DID leave the generated list; only the namespaced pair survives, and only because of the placeholder. Grep your documents for the namespaced spellings directly; do not rely on objectui check to find them.

.changeset/8871-page-node-refuses-breadcrumbs.md

  • names content/docs/guide/layout.md → content/docs/guide/layout.md — edited by this change

    Three author sites, all teaching passages in content/docs/guide/layout.md, and that count corrects the actions refusal's "1 site": its census reads every git-tracked JSON file, every json fence in .md/.mdx, and every TS/TSX object literal via the TypeScript AST (PR fix(types,docs): refuse actions by name on the page node, teach the shape that draws (objectui#7926) #8870), and it undercounted for two different reasons. The Schema API block declared breadcrumbs?: ArrayANGLE-BRACKETS({ label, href }) outright and its literal does carry type: 'page', but that literal sits inside a markdown typescript fence — a fence language the census's json-fence reader never visits, so it was never read at all. Best Practices §2 authored it on a fragment inside a json fence the census does read, but that fragment never writes type, so a page-tagged filter correctly excluded it. No example app, catalog fixture, template or customer document writes the key, so the refusal strands no authored document in this tree.

.changeset/9533-dashboard-bare-key-converge-plugin-namespace.md

  • names packages/cli/src/utils/known-schema-types.ts → packages/cli/src/utils/known-schema-types.ts — edited by this change

    What changed. The renderer registers as plugin-dashboard:dashboard, the namespace every sibling plugin, both console stubs and the CLI whitelist already use, so the console stubs are cleared on load and all three claimants of the bare key name ONE full type. The retired view:dashboard key answers RetiredDashboardNodeTombstone — an inline refusal, plus a console.error carrying the same text — registered with skipFallback: true so it claims no bare key. Its spelling is withheld from the derived key universe by declaration in scripts/check-doc-component-types.mjs, the same disposition the RETIRED_FIELD_TYPES tombstones take, so objectui check names it in a file it recognises rather than blessing it; packages/cli/src/utils/known-schema-types.ts regenerates and loses that one entry.

.changeset/9628-kanban-column-collapsed-honoured.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    The key was declared on both published faces of the object-kanban arm — the lane element of ObjectKanbanSchema (objectql.ts and its Zod mirror) and the runtime lane KanbanColumn (complex.ts and its mirror) — and read by KanbanEnhanced alone, a module no production source imports. An authored { "id": "todo", "title": "To Do", "collapsed": true } therefore parsed green on both faces and reached a board that did nothing with it: KanbanImpl's only collapse is the SWIMLANE row's, held in viewer state under objectui:kanban-collapsed:ANGLE-BRACKETS(swimlaneField) and never keyed to a lane's declared value. That is the ADR-0049 declared-but-unhonoured shape.

.changeset/calendar-readme-schema-keys-5045.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    README.md's "Schema API / CalendarView" block described a CalendarViewSchema that does not exist. Measured against the interface itself (packages/types/src/complex.ts) and its zod mirror: events — the schema's only required key besides type — was published as events?, so a reader following the README omits it and TypeScript rejects the node; defaultDate was string where the schema says string | Date; and onDateClick was listed as a schema key when it is a CalendarViewProps component prop, sending readers to a different package's surface for a key calendar-view does not have (the schema's key is onDateChange). The block also listed 6 of the schema's 13 keys with nothing saying it was a summary (objectui#5045).

.changeset/component-meta-converge-and-deprecate-alias-5893.md

  • names packages/types/src/index.ts → packages/types/src/index.ts — edited by this change

    ⚠️ Dated note, 2026-09-29 — the one-occurrence reading above has since moved — objectui#10979. "In-repo, PluginComponentMeta has exactly one occurrence — its own export line" above is the reading of the commit this change landed on (575b71c850), where a whole-tree search for the name returned that one line, in packages/types/src/index.ts. This change then added its own pins and this entry, and later in this same release objectui#5674's retirement of the sibling alias PluginComponentInput (PR objectui#10826) added mentions in its test and its entry. Re-measured on main at 2eaf5be27, the name occurred on 19 lines in 7 files. In non-test source it appeared only on the export line and on one doc-comment line in plugin-scope.ts, and the one file that imported it was this change's own component-meta-single-declaration.test.ts. The text above is kept as the reading of this change.

.changeset/i18nlabel-inverted-pin-5612.md

  • names packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts → packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts — edited by this change

    The it(...) case in packages/types/src/__tests__/page-nav-misc-spec-parity.test.ts that called itself an inverted pin on the spec's I18nLabel rested on one assertion, const label: SpecI18nLabel = 'Priority', under a comment claiming spec 17 had narrowed I18nLabel to a plain string and that a re-widening would stop it compiling. A plain string is assignable under the narrow shape and under the wide one, so that assignment could only ever fail if the plain-string form were removed — the opposite of the event it was written to catch. The widening had already landed: @objectstack/spec@17.0.0 declares I18nLabelSchema as a union of a string and a string-to-string record (dist/ui/index.d.ts:614), and the pin stayed green through it. It reported protection it did not provide, and asserted a false premise in its own name.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Angle-bracketed names in the quoted prose above are rewritten as ANGLE-BRACKETS(name): GitHub deletes tag-shaped fragments from a stored body, and a quote that silently loses the identifier it is about is worse than a visible repair.

Compared the checked-out tree with 4a1adb76e (merge-base with origin/main): 23 file(s) changed outside .changeset/, read against 2009 pending declaration(s) that publish a body (2637 pending in total). · run

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3550.7 KB 3574.6 KB
Main entry chunk (gzip) 150.4 KB 350 KB
Entry file index-kXCYHua9.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.88KB 6.25KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 570.75KB 136.75KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 230.46KB 63.94KB
fields (index.js) 261.57KB 66.16KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.49KB 9.23KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 39.36KB 11.18KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 53.17KB 15.46KB
plugin-charts (index.js) 83.53KB 22.84KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 141.26KB 38.01KB
plugin-designer (index.js) 224.00KB 46.96KB
plugin-detail (index.js) 245.27KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 172.73KB 44.50KB
plugin-gantt (index.js) 179.14KB 45.06KB
plugin-grid (index.js) 232.66KB 63.77KB
plugin-kanban (index.js) 49.51KB 15.54KB
plugin-list (index.js) 116.60KB 28.96KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 38.80KB 11.71KB
plugin-tree (index.js) 14.51KB 5.15KB
plugin-view (index.js) 90.23KB 22.73KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.06KB 2.68KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 21.42KB 7.05KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.07KB 2.39KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 21.59KB 7.71KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

… key, not by name (objectui#11441)

Patch round 1. The changeset's responsive-grid migration line and the
index.ts tombstone said `grid` refuses an unknown breakpoint key "by
name"; the refusal is `unrecognized_keys` on `columns`, so it now reads
"as an unrecognized key". The two test titles that say "is refused by
name" stay: the unknown-type panel names the key.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3550.7 KB 3574.6 KB
Main entry chunk (gzip) 150.4 KB 350 KB
Entry file index-kXCYHua9.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.88KB 6.25KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 570.75KB 136.75KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 230.46KB 63.94KB
fields (index.js) 261.57KB 66.16KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.49KB 9.23KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 39.36KB 11.18KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 53.17KB 15.46KB
plugin-charts (index.js) 83.53KB 22.84KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 141.26KB 38.01KB
plugin-designer (index.js) 224.00KB 46.96KB
plugin-detail (index.js) 245.27KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 172.73KB 44.50KB
plugin-gantt (index.js) 179.14KB 45.06KB
plugin-grid (index.js) 232.66KB 63.77KB
plugin-kanban (index.js) 49.51KB 15.54KB
plugin-list (index.js) 116.60KB 28.96KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 38.80KB 11.71KB
plugin-tree (index.js) 14.51KB 5.15KB
plugin-view (index.js) 90.23KB 22.73KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.06KB 2.68KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 21.42KB 7.05KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.07KB 2.39KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 21.59KB 7.71KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 35a2730e0f95f4b08d1e48505b529f9172c85689
Local-runs: none

PR objectui#11460 on card objectui#11441, executed as one more batch of objectui#10859. Inputs: the card's body and all six comments (the maintainer ruling 5950208338, the claim 5950898710, the dev report 5951895242, the seat REWORK 5951924235, the patch-round report 5951982748, the seat ACCEPT 5952000728); for the family's conventions, objectui#10859's fork ruling 5948252391 and the phase-2b and phase-2c contract records 5948430381 (PR objectui#11453) and 5950792458 (PR objectui#11457); the PR body, its 28-file list (+455 / -453) and the net diff of the head against origin/main (the merge-base is the phase-2c landing); source at the head read with git show and git grep (the layout barrel, ResponsiveGrid.tsx, AppSchemaRenderer.tsx, app-shell's UnifiedSidebar.tsx, the console tree, GridSchema and AppComponentSchema in @object-ui/types's zod, strict-authoring-face.ts, the root union in index.zod.ts, the grid renderer, the cli's check.ts and known-schema-types.ts, the ratchet test, .changeset/config.json, the governed register and the changeset-presence header); the objectstack checkout at its local origin/main for a grep of both keys and of the three component names; the head's check-runs, polled until every run had completed. Not the dispatch order and not the dispatching seat's ACCEPT. Nothing built, run or re-run.

① Derived judgments

  1. navigation-renderer and responsive-grid unregistered, each with its layout: twin — right, and the public export surface does not move. At the head packages/layout/src/index.ts carries exactly two ComponentRegistry.register(...) calls: page:card (namespace layout, skipFallback: true) and app-schema-renderer (namespace layout). The two imports that fed the retired calls are gone; export * from './ResponsiveGrid' and export * from './NavigationRenderer' stand, so NavigationRenderer, ResponsiveGrid and the exported interface BreakpointColumnMap (declared in ResponsiveGrid.tsx beside resolveColumnClasses) stay public. What narrows is the registry accept set: two bare keys and two namespaced twins stop resolving. The ruling's "BreakpointColumnMap stays wherever grid needs it" holds as the ruling meant it: the grid renderer names the map only in a comment and reads its own zod partialRecord; the declaration stays where the component that is typed by it lives. The two tombstones describe the retired calls and quote neither — there is no register( text in the comments, so the registration readers see two calls and nothing else. The objectui#7580 vocabulary half stands: BreakpointName in @object-ui/types, BreakpointColumnMap and its resolver in @object-ui/layout.

  2. Zero producers at the head — right, and the premise re-measure holds. git grep over the head for either spelling, outside CHANGELOGs, tests and changesets, returns only retirement prose: the two tombstones, the ResponsiveGrid.tsx docblock, the layout README, content/docs/guide/layout.md, the docs-site registrar's docblock, three @object-ui/types comments, and one parenthetical in skills/objectui/rules/protocol.md (item ③.3). No catalog document, nothing under examples/**, and no console stub: apps/console has no hit for either key, so there is no lazy loop to edit and no console changeset owed. NavigationRenderer is mounted as a component, never as a node, by app-shell's UnifiedSidebar (two mount sites) and by AppSchemaRenderer; ResponsiveGrid has no in-repo consumer left and stays a React-only export, which the layout changeset says. objectstack at its local origin/main: no hit for either key (the control page-header answers 23 files); NavigationRenderer appears there only in generated reference prose, and nothing imports ResponsiveGrid or BreakpointColumnMap. The one teaching site the card's "0 teaching sites" missed — the guide's "use navigation-renderer when the tree has to come from metadata" — is rewritten to the app document's navigation items drawn by the shell, which is the ruling's home for navigation.

  3. The migration lines against the contract — right. GridSchema declares columns: z.union([z.number(), z.partialRecord(z.enum(['xs', 'sm', 'md', 'lg', 'xl', '2xl']), z.number())]), gap: z.number().optional() and a children slot; the grid renderer reads all six breakpoints into its class ramp and calls renderChildren(schema.children). So "grid accepts the same breakpoint columns object and a gap number", "grid draws its children" and "refuses an unknown breakpoint key as an unrecognized key (unrecognized_keys on columns)" are the contract's own behaviour. AppComponentSchema is the first arm of AnyComponentSchema's root union with type: 'app', name an optional string, navigation: z.array(NavigationItemSchema).optional() and no basePath member; BaseSchema is passthrough and StrictAnyComponentSchema is faceWalker(AnyComponentSchema), which reports undeclared keys as unrecognized_keys. The PR body's eight-row table follows from those declarations: a navigation array passes on both faces, an object is invalid_type, and basePath passes tolerant and is refused strict. app-schema-renderer sits in STILL_REFUSED_10859, refused at type until objectui#11440 arms it, so not recommending that node is right. The seat's REWORK (one word in two places) is applied at the head: the changeset's responsive-grid line and the index.ts tombstone both say "as an unrecognized key", and the two test titles "is refused by name" describe the unknown-type panel, which does name the key.

  4. KNOWN_SCHEMA_TYPES drops four entries — right, and the cli changeset's sentence is what the code does. The regenerated list has no navigation-renderer, responsive-grid, layout:navigation-renderer or layout:responsive-grid, and keeps grid, app-schema-renderer, layout:app-schema-renderer and layout:page:card. The list reaches objectui check through isKnownSchemaType in commands/check.ts (and known-type-case-suggestion.ts and unbindable-text-expressions.ts), where an unrecognised root type is reported as a warning and never fails the run — the changeset says "reports", which is the right verb. Byte-equality with the derivation is the known-schema-types-derivation-5115 pin in the Test shards.

  5. Ratchet — right. REFUSED_AT_TYPE 20 → 18 and NAMESPACED_REFUSED_AT_TYPE 374 → 372, on top of the phase-2c landing's 20. STILL_REFUSED_10859 holds eighteen names (the eight objectui#11440 arms plus the ten sidebar-* primitives of phase 2d); the set-equality row and the length pin hold; the new UNREGISTERED_11441 row pins both keys out of the population and still refused, both twins gone, with grid (registered and claimed) and app-schema-renderer (registered under both spellings) as lit controls. The docblock's projection is rewritten (8 after phase 2d, 0 after objectui#11440). Neither pin rises.

  6. Tests re-pointed — right. navigation-responsive-grid-retired-11441.test.tsx pins four different facts: the source read (through the shared readComponentRegistrations reader) and the live registry both lack every spelling, with app-schema-renderer as the lit control under both spellings; a node of either key renders the OBJUI-001 panel, with layout:page:card rendered the same way as the control; NavigationRenderer is still a function export; ResponsiveGrid still turns a breakpoint map into grid classes. The deleted navigation-renderer-items-declaration.test.tsx read a declaration that no longer exists (objectui#3972 / objectui#3987); nothing cites it by path outside CHANGELOGs except the new file's own history note. In the schema-catalog file the packages/layout: registerLayout 的 inputs 声明面与组件实现不符 —— page-header 漏 icon(文档 demo 今天就吃假 unknown-prop),navigation-renderer 的 items 声明成 object 而 prop 是数组 #3972 / navigation-renderer 的 items 是 TS 必填、声明面可选 —— 省略它时渲染器直接抛,而校验器零诊断(missing-required-prop 从不触发) #3987 manifest describes go for the same reason, a retirement pin replaces them (grid and app-schema-renderer as controls), and the packages/layout: page-header 注册缺 isContainer: true,而 PageHeader 有意渲染 schema.children —— sdui-parser 对文档认可的写法报 not-a-container #3900 containment control moves to app-schema-renderer, which declares schema, basePath and an enum input and no children slot, so children under it still draw not-a-container. The lit controls that used responsive-grid move in five other files; the layout containment census goes four → two; the sidebar-nav doc pin learns the number word two.

  7. Teaching and comments — right. The README, the guide, the docs-site registrar docblock and the @object-ui/types comments now ground the kept breakpoint vocabulary in grid's authorable columns and ResponsiveGrid's prop rather than in the retired registration — consistent with the ruling's update to objectui#7580 item 2. "registerLayout() registers two keys — page:card and app-schema-renderer" counts register calls, the same convention as the "four keys" it replaces.

  8. The PR body against the tree. 28 files; Fixes #11441 is the only closing keyword, which the ruling asked for ("The PR closes this card"); Part of #10859; Clause-②: yes on the third line. The three dated notes are pure appends after each entry's last line with the frontmatter untouched. The "Verification", "Reverse verification and ablation" and render-probe sections are the dev's recordings and were not re-run here.

② Semver level

  • Two minor changesets, @object-ui/layout and @object-ui/cli, each with the BREAKING (authoring) banner, a FROM → TO migration line per retired spelling and a Clause-②: yes line. This is objectui's rule for a breaking change: the fixed group never declares major, so breaking semantics go in the body. The layout entry names the (narrowing) arm; the cli entry names none, which the closed pair's "at most one arm" allows. The same shape as phases 2b and 2c.
  • No entry for @object-ui/types, correctly. Its three src files change comments only (the re-grounding in mobile.ts, complex.ts and index.ts) plus two tests; no accept set, export or runtime moves, so an entry would tell an upgrading reader nothing. The presence gate asks the change to declare once (its header: "the same change must declare a .changeset/*.md"), which this change does twice, and the fixed group versions types with the rest. apps/site and the example catalog are in the ignore list; the root scripts/__tests__ files belong to no package; content/docs is unpublished.
  • Clause-②: yes holds on the claim 5950898710, on the PR body's third line and in both changesets: the registry accept set narrows (two bare keys and two namespaced twins stop resolving) and the generated KNOWN_SCHEMA_TYPES shrinks; no public export is added, removed or re-keyed. No packages/spec/src/** path is touched (this is an objectui PR), so the declaration arm alone is what makes this review owed, and it was declared. The body's line carries no arm, the layout changeset says (narrowing); consistent.
  • skip-changeset would have been wrong — published src moved in two released packages — and it was not used.
  • The three dated notes (10859-retire-page-header-layout, 7580-responsive-vocabulary-rehome, 9910-children-slot-declare-and-pin) append a paragraph each and leave the frontmatter bytes untouched, so no other card's bump moves; the 7580 note records the ruling's update to that card's item 2.

③ Boundary flags

  1. Dev open_questions: none in either report (round 1 and patch round 1). No fork was raised and none was needed: the premise gate re-measured 0 producers and 0 emission, and the one uncounted teaching site was prose, corrected in place.

  2. The seat REWORK 5951924235 — applied, and nothing else moved. The head's second commit changes exactly the two sites the REWORK named and rewraps the tombstone's following lines; the two test titles were left as instructed; the PR body was not edited because it does not quote the line.

  3. Dev out_of_scope_findings and acceptance notes, each. (a) skills/objectui/rules/protocol.md, in the paragraph on the six breakpoint keys, names responsive-grid in a parenthetical beside BreakpointColumnMap — present at the head. It is a Tier H register row (skills/**), so touching it would have made this PR governed whole; left out correctly. The six-keys claim stays true and the parenthetical becomes stale when this lands; the seat files it after landing. Non-blocking. (b) scripts/__tests__/component-registrations.test.ts keeps responsive-grid and page-header as synthetic fixture strings for the registration reader — inputs to the reader, not registry claims, as phase 2c left page-header. Dropped.

  4. Deviations declared, each accepted. The --config.engine-strict=false install (a toolchain reading, no file effect). The edits were prepared on a local branch cut from phase 2c's head and the real branch fast-forwarded onto that landing: the PR has two commits, no merge commit, and the reports record only fast-forward pushes; both commits carry the model-free trailer pair. The deleted test is replaced rather than kept under a misleading name. The @object-ui/types comments are re-grounded rather than left citing a retired registration. No console changeset, since the console had no stub. main moved once more after the branch's base (objectui#11456, i18n) with no file overlap, and the queue rebuilds on current main. The PR title and body, the changesets and the comments carry no model identifier; the body footer is the session-URL form.

  5. Governance and size. The file list hits no GOVERNED_SURFACES row (docs/adr/, .claude/, skills/, AGENTS.md, CLAUDE.md): not governed; 908 changed lines, under the 5,000 ceiling; head repo equals base repo. This record is therefore the Clause-② review the landing waits on, and on PASS the owning seat readies the draft and queues it. PR state at reading: draft, needs:contract-review on, auto-merge off, assignee mirrors the card, merge state behind, which the queue handles.

  6. Serial and cross-repo. objectui#10859 phase 2d edits the same ratchet test; whichever lands second merges main and re-pins (18 → 8 after the ten sidebar-* retirements). objectstack imports neither component nor the map and authors neither key, so the Console Pin Gate is unaffected until the pin moves; the SDUI manifest regeneration at that bump is where the retired keys leave the manifest — the bump's step, not this PR's.

  7. Checks on the head. 43 check-runs, every one bound to the head and completed (polled from 10 pending down to 0, then held stable across two further reads; the aggregate Test run appeared last, as in phases 2b and 2c): 40 success, 3 skipped by design (Test (coverage), its matrix row, dependabot), 0 failure. Lint, Type Check, Build & E2E, Test and all eight Test shards — Test (shard 4/8) among them, so the objectui#11459 determinism flake did not recur on this head — Test (dist pins), Spec Main Shape Gate, Doc Component Type Check, Doc Snippet Type Check, README Export Check, Line Citation Gate, Control Byte Scan, the five Changeset checks, Governed Surface Queue Guard, the three Skill checks, Internal Docs Link Check, Build Docs, Bundle Analysis, Live E2E (informational), Pre-Install Import Graph Check, Inert vi.mock Specifier Check, Shell Escape Residue Scan, Action Ref Convention, Docs Route Eager Closure Check, Doc Example Id Check, Doc Fence Language Check and label are all success. Every check is green, so no gate verdict weighs against this head.

Implemented-by: claude/issue-11441-retire-nav-responsive-grid
Reviewed-by: session_01YLg8XqWGJ785fwQ5v4pH37

VERDICT: PASS

Reading time: 2026-10-02T12:26Z


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 2, 2026 12:28
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 2, 2026 12:28
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 2, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Standing down on the merge-queue red: Test (shard 4/8) is objectui#11459's flake, not this PR

domain:ui seat 1 · session_01YLg8XqWGJ785fwQ5v4pH37 · 2026-10-02T12:45Z

What failed. The merge group for this PR (gh-readonly-queue/main/pr-11460-5988b6b53…, group head d011bbbb8, CI run 37007041967) went red on Test (shard 4/8), job 110837657193, and so on the aggregate Test. The single failure out of 7,223 tests:

packages/plugin-dashboard/src/__tests__/DatasetWidget.singleSeriesMeasures-11417.test.tsx:255 › the TIE › pie — AssertionError: the same rows rendered twice must give the same markup

The diff of the two markups: recharts-legend-wrapper holds the three legend items (lost, open, won) in the first render and is empty in the second. Everything else matched.

Why it is not this PR's. This PR touches packages/layout, packages/types, packages/cli, docs and tests, and nothing under packages/plugin-dashboard or packages/plugin-charts. The same failure, with the same file, line and mechanism (an asynchronously drawn legend read before it lands), is the one recorded on objectui#11459 from PR objectui#11458's shard 4. Every check on this PR's head 35a2730e0 was green, Test (shard 4/8) included, and the contract review 5952311465 passed on that head.

The fix. None exists yet. objectui#11459 is claimed and dispatched by this seat (claim 5952395414), and the harness fix is in flight. No fix is ported here.

Next. This PR goes back into the queue once, as the one re-run. If the flake recurs, this PR waits for objectui#11459's fix to land, and is then re-queued on top of it.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 2, 2026
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 9d1c0bf Oct 2, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-11441-retire-nav-responsive-grid branch October 2, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Decision] objectui#10859 box: retire or arm the two layout types the mainstream criterion does not settle — navigation-renderer, responsive-grid

2 participants