Skip to content

refactor(components)!: the sidebar node supplies its own provider; retire the ten sidebar-* primitives; the sidebar documents teach the node (objectui#10859 batch 8, phase 2d) - #11463

Merged
objectstack-fleet[bot] merged 10 commits into
mainfrom
claude/issue-10859-batch8-phase2d
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 10 commits into
mainfrom
claude/issue-10859-batch8-phase2d

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Part of #10859

Clause-②: yes

Phase 2d of batch 8 on the family card, under "Fork 3" of the seat's fork ruling 5948252391 (route A, conditional). The sidebar registration now mounts its own SidebarProvider only when no provider is above it. The four components-basic-sidebar catalog documents and sidebar.mdx teach that node. The sidebar registration honours the spec's boolean collapsible. The ten sidebar-* primitives retire. Implemented by os-dev for domain:ui seat 1, session session_01YLg8XqWGJ785fwQ5v4pH37. Base: origin/main 5988b6b53. Main was merged after objectui#11457 (phase 2c) landed as ad1785c1d, and again after objectui#11458 landed; neither merge touched this PR's files. objectui#11441 (PR objectui#11460) landed first, so on the merged base this PR moves the ratchet 18 → 8.

Premise, verified first: safe detection exists

shadcn's useSidebar() throws outside a provider, and its context is private to the primitive. The primitive gains useOptionalSidebar(), a non-throwing read that returns null exactly where useSidebar() would throw. It is added as a declared local patch in scripts/shadcn-local-patches.mjs (two anchored edits on registry bytes: the reader and its export). The no-touch rule for src/ui/** is kept. The SDUI node wraps only when that read returns null.

Both cases from the ruling were measured through the real SchemaRenderer. A provider is counted by its group/sidebar-wrapper element.

host providers in the tree whose state drives the node
bare (no provider) 1, the node's own the node's own provider (expanded)
controlled SidebarProvider, open false then true 1, the host's the host: data-state goes from collapsed to expanded
@object-ui/layout AppShell with defaultOpen false and a SidebarTrigger in its navbar 1, the shell's the shell: starts collapsed, and clicking "Toggle Sidebar" makes it expanded

The tests that pin these cases are sidebar-node-provider-10859.test.tsx in @object-ui/components and app-shell-sidebar-node-one-provider-10859.test.tsx in @object-ui/layout. Ablation 1 below forces the detection off, and every host-with-provider row goes red. There is no fork, so neither fallback route (B or C) is used.

collapsible: the boolean is honoured

false maps to shadcn's 'none': the in-flow, fixed-width form, which ignores the open state. true or an absent key passes no prop, so shadcn keeps the default the node applied before (offcanvas). Before this change, the boolean reached the DOM verbatim as data-collapsible="true" / "false", which no rule matches. A render pins each value (false → in-flow; true / absent → offcanvas; never the verbatim boolean). Any other value is forwarded unchanged, as before, and objectui validate refuses it as invalid_type at collapsible (measured for 'none' and 'icon'). The registration's collapsible input is now declared as a boolean. Its defaultProps no longer name collapsible: that 'icon' was never read at render, because SchemaRenderer does not read a registration's defaultProps.

The teaching: four documents and sidebar.mdx

Each document is now one { "type": "sidebar", "collapsible": false, "children": [...] } node, with armed children:

  • basic-sidebar and grouped-sidebar: text headings and ghost button items, and in grouped-sidebar a separator between the groups;
  • collapsible-sidebar: three button items;
  • sidebar-with-badges: flex rows with their children in properties (objectui#11276), each holding a text node and a badge node. The 6806 pins ("Inbox12", "Drafts3", two labelled badges) still hold.

The documents author collapsible: false because that is the one form that draws in every host. The docs-site hosts mount their provider with defaultOpen={false}, so a collapsible-form document starts collapsed and off-canvas there. collapsible-sidebar keeps its id. Its curated title is now "Non-Collapsible Sidebar", with a description, because the old title named a behaviour the document does not show.

Measured by a render: sidebar-node-docs-10859.test.tsx renders each document bare and inside the docs-host shape (SidebarProvider with min-h-0 w-full and defaultOpen={false}). In both shapes the test checks exactly one provider, the in-flow form, every authored string, and no diagnostic panel.

Measured in a browser: the real renderer's markup was compiled with the repo's Tailwind 4.3.3 and laid out in Chromium at 1280×800. basic-sidebar occupies x 16 to 272, 256 px wide and hit-testable, both bare and in the docs host. At 375 px the same holds.

Measured by objectui validate: the built CLI's validate command returns exit 0, "Schema is valid!", for all four documents. As a control, the base basic-sidebar.json returns exit 1, invalid_union at type. The strict face (StrictAnyComponentSchema) accepts all four too.

sidebar.mdx now describes the node and the two collapsible values, and its Schema block is a typed SidebarSchema literal. That literal validates on both faces. check:doc-snippets judges it: with collapsible set to 'none', the gate reported 1 failed block, a TS2322 on that line, and at head it reports 0 failed. The page no longer lists the items / groups keys, which no face declares.

Retirement: the ten sidebar-* primitives

The premise gate was re-measured at origin/main ad1785c1d / 4a1adb76e and objectstack origin/main ecb6ca02, at a type position, for both spellings:

  • objectui producers: only the four catalog documents, which are rewritten here.
  • objectstack: 0.
  • Runtime emission (computed sidebar- keys): 0 in either repo.

sidebar-provider, sidebar-header, sidebar-content, sidebar-group, sidebar-menu, sidebar-menu-item, sidebar-menu-button, sidebar-footer, sidebar-inset and sidebar-trigger are unregistered, with their ui: twins. One tombstone docblock in renderers/navigation/sidebar.tsx describes the retired calls without quoting them, so the node-slot source reader does not mistake them for live calls. The shadcn components behind the ten stay exported for JSX.

Tests that named the retired keys moved with them:

  • The DOM-leak sweep loses 10 targets (150 / 82 / 68 for components; 168 targets and 84 rows overall), and its count prose follows. The "ui:sidebar-trigger is CLEAN" case goes, because there is no registration left to sweep; the ratchet pins the absence.
  • sidebar-trigger-dom-leak-5632.test.tsx is deleted with its subject. The sweep's historical note gains a dated line.
  • In the form-control leak census, sidebar-menu-button leaves and button goes from 116 to 127 (the new items). In the layout leak census, flex goes from 248 to 252, text from 699 / 155 to 687 / 140 and box from 86 to 82. Each move has a comment explaining it.
  • The container-declaration census drops both sidebar context probes. sidebar now renders its child under the bare probe, and that is asserted. The ruled-family row is now button, badge, alert and sidebar.
  • The sidebar-group inline-locale read-site cases go, with a dated note. The body-dialect census pin now reads the one remaining registration.
  • shadcn-local-patches.test.ts filters the cookie family by issue and adds the optional-context family.

Ratchet

pin before after what moved
REFUSED_AT_TYPE (bare) 18 8 the ten sidebar-* keys
NAMESPACED_REFUSED_AT_TYPE 372 362 the ten ui:sidebar-* twins

STILL_REFUSED_10859 now holds the 8 the ruling kept (objectui#11440), and its set-equality row holds. objectui#11441's row and this phase's row both stay. A new phase-2d row checks three things: the ten keys are out of the population and still refused at type, their twins are gone, and sidebar is registered and not refused. ui:sidebar is still registered, and it stays among the namespaced keys objectui#10872 counts as refused, so the row asserts only that it is present. The namespaced non-vacuity floor goes from 400 to 350 (391 keys now), with a comment. ⛔ Neither pin rises. objectui#11441 landed first, so this PR merged main (ed54d285c) and re-pinned at 2095abad1.

Changesets

  • @object-ui/components, minor, BREAKING (authoring): the ten keys, with a migration per spelling. Each target was measured to validate on both faces: sidebar with className; button with variant: "ghost"; text; separator; a flex row holding text and badge; and a flex row holding the sidebar node and a box.
  • @object-ui/components, minor: the provider detection, the collapsible mapping and the new useOptionalSidebar export.
  • @object-ui/cli, minor, BREAKING (authoring): the regenerated known-types list.

layout, app-shell and example-schema-catalog changed test files or private content only. Five pending entries gain dated notes: 11347, 5632-sidebar-trigger-dom-passthrough, 6771, 9910 and form-control-renderers-dom-props-5632. Each note is a pure append.

Local runs (final head a27ff4385)

  • Re-pin round at 2095abad1 (dev report 5954519792 on objectui#10859). After merging main d93e53f5d:

    • every test file this PR touches, plus the known-types derivation and six readers: 18 files, 1035 tests, all passed;
    • regenerate-known-schema-types --check: OK;
    • the changeset, claims, line-citation and control-byte checks: exit 0;
    • the cli / components type-checks: Done.

    The runs below were taken at a27ff4385.

  • Final pin union at a27ff4385 (through os-verify-lock, vitest run --maxWorkers=2): the 7 pins plus the catalog gallery, both catalog leak censuses, the 6806 file, the DOM-leak sweep, the inline-locale and cookie-restore tests, the catalog-index and known-types derivation tests, the types node-slot reader, the CLI known-types test, and the three designer tests objectui#11458 brought in (designer-zod-arms-10859 among them). Result: Test Files 21 passed (21), Tests 1098 passed (1098), VERDICT command-exit 0.

  • At 21b03a578 (before the last merge; this PR's files differ from the final head only in the sidebar-node-provider-10859 test file):

    • packages/components in full, in three calls: 154 passed, 98 passed | 1 skipped, 100 passed files.
    • examples/schema-catalog/: 39 files. The one red was the layout census, which was then updated.
    • packages/cli/ and packages/layout/ plus the layout census and five readers: 65 files.
    • 23 script and app-shell sidebar-host tests.
    • All green.
  • Exit 0 at a27ff4385:

    • check-changeset-presence (9 source files of 4 released packages, 3 changesets);
    • docs:check-links, markdown-test-inputs --audit, regenerate-known-schema-types --check, regenerate-catalog-index.py --check;
    • changeset:check, check:changeset-claims, check:component-surface-parity, check:control-bytes;
    • check:doc-example-ids, check:doc-example-readers, check:doc-examples, check:doc-fences, check:doc-types, check:doc-snippets;
    • check:element-data-source-declaration, check:handler-key-reads, check:new-line-citations (0 new), check:pending-changeset-literals, check:prompt-keys, check:readme-exports;
    • check:registry-bare-names, check:self-import, check:side-effects-array, check:spec-symbols, check:test-path-roots, check:unreferenced-sources;
    • check:vi-mock-inherit, check:vi-mock-specifiers, check-vi-mock-override-shape, check-lint-coverage;
    • pnpm check (the built CLI's self-check: 287 validated, 0 did not validate);
    • check:sdui-registration-pins (16 of 16).
    • Builds, redone after the last merge: the doc-snippet turbo closure with cli..., and @object-ui/console....
    • objectui validate (built CLI): exit 0 for the four documents, and exit 1 for the base basic-sidebar.json.
  • Type-check at a27ff4385: components, cli, layout, example-schema-catalog and app-shell are Done, including each package's test tsconfig. Counted with --listFilesOnly, the new and edited test files are inside those configs.

  • ESLint, narrowed, at a27ff4385: eslint --format json over the 16 changed ts/tsx/mjs files, the way each package's eslint . runs it, gives 0 errors and 5 warnings. The 13 files that exist at base give 0 errors and 13 warnings on their base blobs; the other 3 are new. The population is the root eslint.config.js, and all 16 files were linted with none ignored. That config sets no projectService / parserOptions.project (0 matches), so no untouched file's verdict can move. Full turbo run lint is CI's.

  • Not run: shadcn:check, which needs the registry over the network. The offline anchor tests in shadcn-local-patches.test.ts cover the new patches.

Reverse verification

The predictions were written before any leg ran.

BASE leg. Ten source files went back to 4a1adb76e: the renderer, the primitive, the patch list, the known-types list, the four documents, catalog-meta.json and index.ts. The 7 pins ran against them.

  • Predicted: 32 red, as 6 + 0 + 16 + 2 + 4 + at least 2 + 1 across the seven pins. The AppShell pin stays green, because base never wrapped.
  • First run: 31 red. The one short was the collapsible: false row: on base it rendered nothing (a bare throw), and nothing has no data-collapsible either. The rows now assert that the node drew before reading its form (commit 000ce424c).
  • Re-run: Tests 32 failed | 104 passed (136), exactly as predicted. The AppShell pin was green.
  • Restored: 10 blobs equal HEAD, git diff HEAD is 0 lines, and status is 0 lines.

Ablation 1: provider detection forced off (the node always wraps). The anchor went from 1 hit to 0, and the blob from 3141c810ecba to b66caf1c8051.

  • Predicted: 7 red, all host-with-provider rows (2 in the node pin, 1 AppShell, 4 docs-host).
  • Observed: Tests 7 failed | 18 passed (25), exactly those 7. No bare-host row moved.

Ablation 2: collapsible mapping removed (the authored value forwarded verbatim). The blob went from 3141c810ecba to 72f62c65ab53.

  • Predicted: 12 red (4 in the node pin, 8 in the docs pin), with AppShell green.
  • Observed: Tests 12 failed | 13 passed (25), exactly those 12.

Both ablations ran through scripts/ablation-replace.mjs, with a trap restore of their own. Restored: blob 3141c810ecba equals HEAD and git diff HEAD is empty after each leg.

Acceptance notes

  • The collapsible form is off-screen on desktop while expanded (out of scope, reported to the seat). shadcn's offcanvas rules (the gap's w-0 and the container's negative left / right) are not qualified by state. The repository's undeclared local edit (3) keeps data-collapsible set while expanded, where upstream blanks it. So an expanded off-canvas sidebar sits off-screen at md and wider. That falsifies the edit's "same result" note in shadcn-components.json.
    • Chromium, 1280 px, with the real markup and Tailwind 4.3.3: a bare { type: 'sidebar' } (collapsible absent or true, expanded) sits at x −256 to −1, out of the viewport. The same markup with the attribute blanked as upstream does sits at x 0 to 255. A collapsible="icon" sidebar, whose rules are qualified, sits at x 0 to 255.
    • Every in-repo JSX host uses icon. The taught documents author false. This PR keeps the ruling's "true or absent → the current default". sidebar.mdx describes the collapsible form only as positioned against the viewport and does not claim that it opens visibly.
  • Declared but not drawn. SidebarSchema declares title, nav, content, footer, position, defaultCollapsed, collapsed, width, collapsedWidth and a variant enum that differs from shadcn's. All of these validate on both faces, but the renderer reads only collapsible, children and className, and spreads the rest onto shadcn. @object-ui/types' README still teaches sidebar.nav. This belongs to the same "declared means enforced" family as collapsible; the docs here teach only what is read.
  • sidebar.mdx now teaches collapsible: false throughout. The ruling's sentence "a bare sidebar node draws visibly in any host" holds for that form, measured in jsdom and Chromium. For the collapsible form it is limited by the first note.

Generated by Claude Code

claude added 8 commits October 2, 2026 11:09
…en none is above it, and honours the boolean collapsible (objectui#10859 batch 8, phase 2d)

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…ebar node; tests stop naming the retired sidebar parts (objectui#10859 batch 8, phase 2d)

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…d dated notes for the retired sidebar parts (objectui#10859 batch 8, phase 2d)

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…debar documents (objectui#10859 batch 8, phase 2d)

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…ading its form (objectui#10859 batch 8, phase 2d)

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

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 7 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/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/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/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/8802-8257-8008-kanban-gantt-family-retirement.md

  • 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/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.

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 d93e53f5d (merge-base with origin/main): 23 file(s) changed outside .changeset/, read against 2012 pending declaration(s) that publish a body (2641 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) 3551.0 KB 3574.6 KB
Main entry chunk (gzip) 150.3 KB 350 KB
Entry file index-ChtiQ9Fb.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) 568.78KB 136.60KB
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.82KB 11.27KB
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) 231.28KB 48.76KB
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: a27ff438552006b19bfddb01ba543ccbbea7f251
Local-runs: none

PR objectui#11463 on card objectui#10859, batch 8 phase 2d (fork 3 of the seat's fork ruling 5948252391, route A conditional). Inputs: the card's body and all 65 comments, every one read in full (the per_page=100 page came back short at 65, so the set is closed; among them the triage 5860727647, the split 5861157913, the batch-8 claim 5945225235, the phase-1 report 5945491717, the seat ruling 5945530142 and its amendment 5945583855, the phase-2b report 5948183744 whose fork 3 this PR executes, the fork ruling 5948252391, the phase-2d report 5953589147 and the seat ACCEPT 5953727841); for the family's conventions, the phase-2b, phase-2c and objectui#11441 contract records 5948430381, 5950792458 and 5952311465; the PR body, its 31-file list (+1020 / -1195) and the net diff of the head against the merge-base 5988b6b53 (main after objectui#11458; three merges of main sit in the branch, and the net diff is what was judged); source at the head read with git show and git grep (the sidebar renderer and the shadcn primitive, the components barrel, SidebarSchema on both faces in @object-ui/types, AppShell, the three docs-site demo hosts, shadcn-components.json, the patch script and its test with the sidebar.registry.txt fixture, the body-dialect census script and test, known-schema-types.ts, the ratchet, .changeset/config.json, the governed-surface register, the types README, the console tree, every commit message); the objectstack checkout at its local origin/main for a grep of the ten keys; the head's check-runs, polled at one-minute intervals from 19 in progress down to 0, with the aggregate Test appearing last. Not the dispatch order and not the dispatching seat's ACCEPT. Nothing built, run or re-run.

① Derived judgments

  1. The premise of the conditional ruling is met, and the detection is safe — right. useOptionalSidebar() is one React.useContext(SidebarContext) function beside useSidebar() in packages/components/src/ui/sidebar.tsx, exported from the primitive's export block; it answers null exactly where useSidebar() throws, because both read the same module-private context. SidebarNode calls it above the provider it may create, so the read sees only a host's provider and never its own: a host with a provider is never wrapped, a host without one gets exactly one. AppShell in @object-ui/layout imports SidebarProvider from @object-ui/components and mounts it (defaultOpen honoured), so the shell's context is the one the node reads; the three docs-site hosts (InteractiveDemo, LiveSplitDemo, SchemaThumbnail) mount SidebarProvider className="min-h-0 w-full" defaultOpen={false}, which is the shape the catalog test reproduces. The pins measure what the ruling asked: one provider wrapper and the host's open driving data-state (components pin), one provider and the shell's own trigger expanding the node (layout pin), one provider in both host shapes for all four documents (catalog pin). The ruling's prohibition ("don't wrap unconditionally") is honoured by construction and by the dev's ablation 1, which the record does not re-run.

  2. The detection is a declared local patch, held offline — right. scripts/shadcn-local-patches.mjs gains two anchored edits on registry bytes (sidebar-optional-context-reader, anchored on the tail of useSidebar's body and the SidebarProvider declaration; sidebar-optional-context-export, anchored on the export block's last entry), each with a marker and occurrences: 1. The generic rows of shadcn-local-patches.test.ts apply every family's declared patches to its captured registry fixture, require zero failed anchors, applied equal to the family's patch count (now four for sidebar) and verifyLocalPatches clean; sidebar.registry.txt exists and carries no useOptionalSidebar, so the fixture was not captured from the patched side. The new family-specific rows pin the two ids by issue and that the family declares no patch outside the two issues. The no-touch rule on src/ui/** holds: the shipped file's only change is the patch's own payload, byte for byte what replace writes.

  3. collapsible honoured as the spec's boolean — right. SidebarSchema.collapsible is boolean on the TypeScript face (navigation.ts) and z.boolean().optional() on the zod mirror (navigation.zod.ts), so objectui validate refuses any non-boolean at collapsible as invalid_type. toShadcnCollapsible maps false to 'none', which the primitive renders as a plain in-flow column with no data-collapsible and no data-state (so the pins' [data-collapsible]-is-null discriminator is the right one and the in-flow form ignores the host's open state); true or absent passes no prop, so the primitive's default offcanvas stands, which is the ruling's "the renderer's current default behaviour". SidebarNode destructures collapsible off the props bag, so the authored boolean never reaches the DOM verbatim; every other authored key still spreads onto the primitive as before. The registration's collapsible input is now boolean, and the unread defaultProps.collapsible: 'icon' is dropped (the renderer's defaultProps are not read by SchemaRenderer; the behaviour before and after is the primitive's default). Right.

  4. The four catalog documents and sidebar.mdx teach the node, and the teaching is true at the head — right. Each document is one { "type": "sidebar", "collapsible": false, "className": …, "children": [...] } with text, button (variant: "ghost"), separator and, in the badge demo, flex rows carrying their children in properties (the authored flex contract since objectui#11276). All four validate on both faces and draw in both host shapes (the catalog pin), and no sidebar-* key remains anywhere under examples/**, content/**, skills/**, apps/** or a package README at the head. sidebar.mdx describes exactly what the renderer reads (collapsible, children, className), teaches collapsible: false as the form that draws in every host, says plainly that the collapsible form is positioned against the viewport rather than drawn where the schema places it, and replaces the fictional items / groups interface with a typed SidebarSchema literal that check:doc-snippets judges. The collapsible-sidebar document keeps its id (the mdx embed and gallery paths depend on it) and gains the curated title "Non-Collapsible Sidebar" with a description, in catalog-meta.json and the generated index.ts; the id/title mismatch is a cosmetic residue of keeping the embed path stable. Right, non-blocking.

  5. Ten node keys unregistered with their ui: twins, zero producers — right. At the head renderers/navigation/sidebar.tsx holds one ComponentRegistry.register('sidebar', …) call and one tombstone docblock that describes the ten retired calls without quoting them (the @object-ui/types node-slot reader mistakes a quoted call in a comment for a live one; the phase-2c precedent). The shadcn components behind the ten stay exported for JSX. Grep of the head for any of the ten spellings at a type position outside tests, changesets and changelogs returns only scripts/body-dialect-census.mjs's population list (item 8). objectstack at its local origin/main: zero hits for any spelling. The retirement follows the objectui#10393 / objectui#8760 route the ruling named.

  6. KNOWN_SCHEMA_TYPES drops twenty entries and the ratchet moves 20 → 10 and 374 → 364 — right. The regenerated list loses the ten bare keys and the ten ui: twins and keeps sidebar and ui:sidebar. STILL_REFUSED_10859 holds exactly the ten the rulings left registered (the eight objectui#11440 keys plus navigation-renderer and responsive-grid); the set-equality row holds; the new phase-2d row pins each of the ten out of the population and still refused at type, each twin gone, sidebar registered and claimed, and ui:sidebar present (still counted among the namespaced refusals objectui#10872 tracks, so presence alone is asserted, which is the honest pin). The namespaced non-vacuity floor moves 400 → 350 with 393 keys remaining; a floor, not the pin. Neither pin rises. Byte-equality of the list with the derivation is the known-schema-types-derivation-5115 case in the Test shards, green on the head.

  7. Tests that named the retired keys moved with them, and the arithmetic is consistent — right. DOM-leak sweep: ten ui:sidebar-* targets leave (eight plain container parts, which were ledgered in the bare-spread group, and the two specials ui:sidebar-trigger / ui:sidebar-menu-button, which were clean), so components goes 160 → 150 targets, 90 → 82 ledgered, 70 → 68 clean, 141 → 133 plain, 157 → 147 ready-matched; overall 178 → 168 and 92 → 84; 10 = 8 + 2 in every row, and the docblock-count pins read the same numbers. ui:sidebar stays under the SidebarProvider host and now uses it. The "ui:sidebar-trigger is CLEAN" case goes because there is no registration left to sweep, and sidebar-trigger-dom-leak-5632.test.tsx is deleted with its subject; the ledger's history note is dated. Form-control census: sidebar-menu-button leaves, button 116 → 127 (basic 4 + grouped 4 + collapsible 3). Layout census: flex 248 → 252 (the four badge rows), text 699 → 687 and 155 → 140 (19 bare labels and "Main content area" strings become 3 classed headings and 4 bare labels: 699 − 19 + 7 and 155 − 19 + 4), box 86 → 82 (the four sidebar-inset padding boxes). Container-declaration census: both sidebar context probes go, sidebar is asserted to render its child under the bare probe and to be absent from CONTEXT_PROBES, the family row becomes ['sidebar'], the ruled set button, badge, alert, sidebar, and the sidebar-trigger control that named two retired keys is replaced by that assertion. The inline-locale sidebar-group cases go with a dated header note; two read sites remain in the package.

  8. The body-dialect census — accepted as a historical population, with one observation. scripts/body-dialect-census.mjs keeps the ten names in BODY_ONLY / RULED_BUT_NOT_A_READER: that list is the population objectui#6771's retirement was measured over, consumed only as --keys defaults and report group headings, and its own comment already speaks in the past tense. The test's source pin is re-pointed to the one live registration (register('sidebar', , no register('sidebar-, one renderChildren(schema.children), zero schema.body) with a dated note, and its public-blocks row keeps asserting that none of the ten bare names became public. Right for a census that records what was retired. The script's list itself carries no dated line saying the ten are now unregistered; the test does. Non-blocking.

  9. A new public export, declared. useOptionalSidebar becomes a named export of @object-ui/components (ui/index.ts re-exports ./sidebar; src/index.ts re-exports ./ui). That is a widening of the published surface, and the provider changeset's third bullet declares it. No other export is added, removed or re-keyed: the ten retired registrations were registry keys, not exports.

  10. The PR body against the tree. 31 files, +1020 / -1195; Part of #10859 first, Clause-②: yes on the third line, no closing keyword; three new changesets; five dated notes that are pure appends (each hunk adds lines after the entry's last line; no frontmatter byte moves). The premise table, the ratchet table and the changeset list agree with the tree wherever the tree can answer. The "Local runs", "Reverse verification" and Chromium geometry sections are the dev's recordings and were not re-run here.

② Semver level

  • Three minor changesets, two for @object-ui/components and one for @object-ui/cli. The retirement entry and the cli entry each carry the BREAKING (authoring) banner, a FROM → TO migration line per retired spelling (each target a key objectui validate accepts: sidebar with className, button with variant: "ghost", text, separator, a flex row with properties.children, and the two "no node spelling" lines that name the JSX route) and a Clause-②: yes line; the retirement entry names the (narrowing) arm, the cli entry names none, which the closed pair's "at most one arm" allows. This is objectui's rule for a breaking change: the fixed group never declares major, so breaking semantics go in the body. The third entry (provider detection, collapsible mapping, useOptionalSidebar) is a non-breaking feature and carries neither banner nor Clause-② line, which is right for what it declares; the seat ACCEPT's one-line summary that all three carry the banner and the line overstates that entry, and nothing rests on it. Changeset Declaration, Changeset Bump Policy, Changeset Fixed Group Check, Changeset Claim Re-read and Changeset Overwrite Report are green on the head.
  • No entry for @object-ui/layout or @object-ui/app-shell, correctly: each changed one test file under src/__tests__/ only. @object-ui/example-schema-catalog and @object-ui/site are in the ignore list; content/docs is unpublished; the root scripts/ files belong to no package. The presence gate asks the change to declare once, which it does three times, and the fixed group versions layout and app-shell with the rest.
  • Clause-②: yes holds on the claim 5945225235, in the fork ruling 5948252391, on the PR body's third line and in both breaking changesets: the registry accept set narrows (ten bare keys and ten namespaced twins stop resolving), the generated KNOWN_SCHEMA_TYPES shrinks, a public export is added, and a declared boolean that was inert becomes enforced. No packages/spec/src/** path is touched (this is an objectui PR), so the declaration arm alone makes this review owed, and it was declared. The body's line carries no arm; one changeset says (narrowing); consistent.
  • skip-changeset would have been wrong (published src moved in two released packages) and it was not used.
  • The five dated notes (11347-components-uncast-reads, 5632-sidebar-trigger-dom-passthrough, 6771-retire-body-child-list-dialect, 9910-children-slot-declare-and-pin, form-control-renderers-dom-props-5632) append a paragraph each and leave the frontmatter untouched, so no other card's bump moves; each states only what this phase overtakes in its entry.

③ Boundary flags

  1. Dev open_questions (report 5953589147): none. The fork the ruling anticipated ("if no safe detection exists, report a fork") did not arise: the detection exists (①.1, ①.2), so neither fallback route B nor C was taken, and the premise gate was re-measured at two main heads and in objectstack before the ten were unregistered.

  2. The one place the ruling's text does not hold, judged. The ruling says a bare sidebar node "draws, visibly, in any host". At the head that is true for the form the documents teach (collapsible: false), measured in jsdom by the pins and in Chromium by the dev. For collapsible omitted or true, the dev measured the expanded sidebar off-screen at desktop widths. I read the cause at the head and it is pre-existing and outside this diff: the repository's undeclared local edit (3) in shadcn-components.json sets data-collapsible in every state (ui/sidebar.tsx, the desktop wrapper), while the primitive's offcanvas rules are not qualified by group-data-[state=collapsed]: as the icon rules are, so the "same result" sentence in that file's localEdits note is false for offcanvas. The ruling's own collapsible clause fixes true / absent to the current default, so this PR is right to keep that default, right not to claim visibility for it in sidebar.mdx, and right to report it rather than widen the ruling. The seat filed it as objectui#11464; the console's own sidebar mounts collapsible="icon" and is unaffected. Non-blocking for this PR.

  3. Dev out_of_scope_findings, each. (a) The offcanvas geometry → item 2, objectui#11464. (b) SidebarSchema declares nine members the renderer never draws (title, nav, content, footer, position, defaultCollapsed, collapsed, width, collapsedWidth), its variant enum (default | bordered | floating) is not the registration's (sidebar | floating | inset), and the @object-ui/types README's "Composable" section still teaches { type: 'sidebar', nav: [...] } — read at the head, all true, all pre-existing, none made worse here, and the same "declared means enforced" family the ruling settled for collapsible; the seat filed it as objectui#11465. Non-blocking. (c) The pre-change documents started collapsed and off-canvas in the docs-site hosts, and the rewrite makes them visible → an acceptance note, and a reason the rewrite is an improvement rather than a lateral move.

  4. Deviations declared, each accepted. shadcn:check not run locally (it needs the registry over the network); the offline fixture rows cover the two new anchors (①.2). The vacuous collapsible: false BASE row was made to assert that the node drew first (000ce424c), which is the right repair to a null reading. The three merge commits of origin/main carry git's default message; the five non-merge commits carry the model-free trailer pair, and the PR lands by squash with the landing seat composing the pair. The PR title, body, changesets, comments and the diff carry no model identifier (scanned); the body footer is the session-URL form. The branch name differs from the batch-8 claim's (claude/issue-10859-batch8-phase2d, one branch per phase, as 2b and 2c did) and is the one the dev report names.

  5. Governance and size. The file list hits no GOVERNED_SURFACES row (docs/adr/, .claude/, skills/, AGENTS.md, CLAUDE.md): not governed; 2,215 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, mergeable, merge state blocked (the draft flag and the checks still running when first read).

  6. Serial. PR objectui#11460 (objectui#11441) edits the same ratchet test and is accepted and contract-PASSed; the seat's plan lands it first. If it does, this head's pins (10 / 364) and STILL_REFUSED_10859 (ten names) are stale against main, and the PR takes the re-pin round the seat named (18 → 8 and 372 → 362, the list becoming the eight objectui#11440 keys, KNOWN_SCHEMA_TYPES regenerated); that round produces a new head, and the record then owed is a delta on it, not this one. Cross-repo: objectstack imports no export this PR removes and authors none of the ten keys, 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 and not this PR's.

  7. Checks on the head. 43 check-runs, every one bound to a27ff438 and completed (polled from 19 pending down to 0; the aggregate Test appeared last and completed at 2026-10-02T13:47Z; the set was read stable at 2026-10-02T13:48Z): 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 objectui#11459's DatasetWidget.singleSeriesMeasures-11417 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-10859-batch8-phase2d
Reviewed-by: session_01YLg8XqWGJ785fwQ5v4pH37

VERDICT: PASS

Reading time: 2026-10-02T13:53Z

claude added 2 commits October 2, 2026 14:12
…tch8-phase2d

Merges objectui#11460 (objectui#11441), #11461 and #11462. The ratchet keeps
both retirements (UNREGISTERED_11441 and the phase 2d row) and pins 8 / 362;
the 9910 changeset keeps both dated notes.

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…known-types changeset states the merged base (objectui#10859 batch 8, phase 2d)

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
@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.6 KB 3574.6 KB
Main entry chunk (gzip) 150.3 KB 350 KB
Entry file index-DFGN0FGM.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) 568.78KB 136.60KB
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) 231.28KB 48.76KB
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: 2095abad1c92a92c695a42faaf1f5d51a4147ced
Local-runs: none

Delta record for PR objectui#11463 on card objectui#10859 (batch 8 phase 2d) at its re-pin head. The full record 5953926028 (PASS on a27ff4385) stands for everything this head did not move, and is cited below rather than restated. Inputs: that record and its scratch; the card's three comments since the phase-2d ACCEPT (the objectui#11441 landing 5954423140, the dev's re-pin report 5954519792, the seat's re-pin ACCEPT 5954569692); the PR body as the seat edited it, its 31-file list (+1027 / -1199) and the net diff of the head against the new merge-base d93e53f5d (origin/main, carrying PR objectui#11462, PR objectui#11460 as 9d1c0bff9 and PR objectui#11461), compared file by file with the net diff of a27ff4385 against 5988b6b53; the two new commits and their messages; the merge commit's blobs against both parents; source at the head read with git show (the ratchet test, known-schema-types.ts at the head and at main, the two changesets that moved); 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. What the new head is. Two commits on top of a27ff4385: ed54d285c, a merge of origin/main d93e53f5d (no rebase, no force-push; the branch is a fast-forward of the reviewed head), and 2095abad1, a re-pin commit. main brought three squashes: objectui#11462 (the objectui#11459 flake harness), objectui#11460 (objectui#11441: navigation-renderer and responsive-grid retired with their layout: twins, the ratchet on main at 18 / 372) and objectui#11461 (an approvals spelling in the console). None of the three touches a file this PR's source, docs, catalog or census changes read, so items ①.1 to ①.5 and ①.7 to ①.9 of 5953926028 stand unchanged; the file list is the same 31 paths.

  2. The PR's own diff moved only where the dev says, verified. Comparing the PR-own hunks of every file between the two bases (index lines stripped): 27 of 31 files are byte-identical. Of the four that differ, two differ in content — the ratchet test and .changeset/10859-known-types-phase-2d.md (item 3 and ②) — and two differ in position only: known-schema-types.ts (the same 20 removed lines; the hunk headers and context moved because main had already removed the four layout keys) and .changeset/9910-children-slot-declare-and-pin.md (the same six added lines, now after main's objectui#11441 note). The added and removed lines of those two files hash identical between the old and new diffs. So the dev's "exactly two files" holds in content, and the record names the two repositioned files for completeness.

  3. The merge is a clean union, and the three both-sides files are resolved right. For every file the merge touches, the merge's blob equals one parent's blob except three: the ratchet test, known-schema-types.ts and the 9910 changeset — exactly the files both sides edited. (a) known-schema-types.ts at the head differs from main's by exactly the twenty sidebar-* / ui:sidebar-* lines; the four layout keys are absent, sidebar, ui:sidebar, app-schema-renderer and layout:app-schema-renderer present; the namespaced population is 391 (main's 401 minus ten) and the bare population 171. The dev's zero-diff regeneration is a local reading not re-run here; byte-equality with the derivation is the known-schema-types-derivation-5115 case in the Test shards, judged on the head in ③.5. (b) The 9910 changeset keeps main's responsive-grid note first and this PR's sidebar-* note after it, both as pure appends. (c) The ratchet test keeps both sides: objectui#11441's UNREGISTERED_11441 map and row (with its grid and app-schema-renderer lit controls) and the phase-2d map and row, in that order. One precision on the dev's account: the pins were set to 8 / 362 in the merge commit's resolution (its message says so), and the re-pin commit 2095abad1 changes only the floor comment and the changeset sentence; the head's content is what is judged, and it is right.

  4. Ratchet — right, and the arithmetic closes. REFUSED_AT_TYPE 18 → 8 and NAMESPACED_REFUSED_AT_TYPE 372 → 362 against main's 18 / 372 (verified by content on main in the landing 5954423140): the ten bare keys and ten twins this PR unregisters, no more and no fewer. STILL_REFUSED_10859 is exactly the eight objectui#11440 keys (app-schema-renderer, detail-section, embeddable-form, home, object-pivot, record, spec-report, utility); the set-equality row and the length pin (toHaveLength(REFUSED_AT_TYPE)) hold; the phase-2d row still pins each of the ten out of the population and refused at type, each twin gone, sidebar registered and claimed, ui:sidebar present. The namespaced non-vacuity floor stays at 350 with its comment corrected to 391 keys. The docblocks name both retirements in order and restate the projection as "8 after phase 2d, and objectui#11440 then takes it to 0". Neither pin rises.

  5. The PR body against the tree — right, with two cosmetic residues. The seat's five edits (the base sentence, the ratchet table 18 / 8 and 372 / 362, the STILL_REFUSED_10859 sentence naming the eight and both rows, the floor note at 391, a re-pin bullet under Local runs naming 2095abad1, d93e53f5d and the dev's report) each state what the tree holds; the "If objectui#11441 lands first" sentence became "landed first, so this PR merged main (ed54d285c) and re-pinned at 2095abad1", which is the history. Residues: "Base: origin/main 5988b6b53" still names the branch's original base while the merge-base is now d93e53f5d (the sentence that follows explains the merge), and the "Local runs (final head a27ff4385)" heading now sits above the re-pin bullet, which says in its own words that the runs below were taken at a27ff4385. Neither misleads a reader of the whole section. Non-blocking.

② Semver level

  • Unchanged from 5953926028 in level and shape: three minor changesets, the two breaking ones with the BREAKING (authoring) banner, per-spelling migration and Clause-②: yes, the provider entry non-breaking without either, correctly. The one text change is the cli entry's ratchet sentence, which now reads "objectui#11441 retired its two layout keys first, so on that base this change takes the registered-types ratchet (REFUSED_AT_TYPE) from 18 to 8, and its namespaced twin from 372 to 362" — true at the head (①.4), and the right place to say it, since a changeset states the release-relative fact and main moved under it.
  • objectui#11460's own changesets are untouched (11441-retire-nav-responsive-grid-layout, its 7580 and 9910 notes): the PR's file list is the same 31 paths, and the 9910 file carries main's note byte-identical before this PR's.
  • Clause-②: yes holds as before (accept set narrows by ten bare keys and ten twins, the generated list shrinks, one export added, a declared boolean enforced); the body's third line still carries it, and no packages/spec/src/** path is touched.

③ Boundary flags

  1. Dev open_questions (report 5954519792): one, answered. The dev left the PR body at the pre-merge pins within a one-push, one-comment budget and asked the seat to edit it (option A). The seat's ACCEPT 5954569692 records option A taken through the relay with an identical read-back; ①.5 judges the result against the tree. out_of_scope_findings: none.

  2. The serial condition of 5953926028 ③.6 is discharged. PR objectui#11460 landed first (9d1c0bff9), this PR merged main and re-pinned exactly as that item projected (18 → 8, 372 → 362, the list becoming the eight objectui#11440 keys, the generated list regenerated with no diff beyond the ten keys). objectui#11440 follows and arms the last eight. Cross-repo: unchanged; the merge adds no export objectstack imports and retires none.

  3. Deviations, each accepted. The merge commit carries a descriptive message and the model-free trailer pair this time; the re-pin commit carries the pair; no model identifier in either commit or in the new hunks (scanned). Not re-run by the dev this round, by scope: doc-snippets, sdui-registration-pins, the full components suite and the reverse verification — the PR's source, docs and docs-gate inputs are byte-identical to a27ff4385 against the new base (①.2), and CI on this head runs every gate again (③.5). The seat's correction to its own ACCEPT prose (5954423140: only two of the three changesets carry the banner and the clause line) matches ② of 5953926028.

  4. Governance, size, state. Same 31 paths, no GOVERNED_SURFACES row hit: not governed; 2,226 changed lines, under the 5,000 ceiling; head repo equals base repo. PR state at reading: draft, needs:contract-review on, auto-merge off, assignee mirrors the card, mergeable, merge state blocked (the draft flag and the checks still running when first read). This record is the one the queue guard reads for 2095abad1; on PASS the owning seat readies the draft and queues it.

  5. Checks on the head. 43 check-runs, every one bound to 2095abad1 and completed (polled at one-minute intervals from 10 pending down to 0; the aggregate Test appeared last, taking the set from 42 to 43, and completed at 2026-10-02T14:33Z; the set was read complete at 2026-10-02T14:34Z): 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 flake did not recur and its fix (PR objectui#11462) is now in this head's tree, 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. The Test shards carry the known-schema-types-derivation-5115 byte-equality case and the re-pinned ratchet, so the generated list and the pins are judged green on this head by the gate itself. Every check is green, so no gate verdict weighs against this head.

Implemented-by: claude/issue-10859-batch8-phase2d
Reviewed-by: session_01YLg8XqWGJ785fwQ5v4pH37

VERDICT: PASS

Reading time: 2026-10-02T14:34Z

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 2, 2026 14:37
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 2, 2026
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.

2 participants