Repository navigation
feat(types): the four page: containers take their child list in properties.children, and objectql.zod.ts shares propsBag (objectui#10872, batch 6) - #11222
Conversation
…rties.children (objectui#10872, batch 6) page:card, page:section, page:footer and page:sidebar refuse a node-level children by name and restate body with the same message, which names properties.children, the member their @objectstack/spec row declares. The spec's own PageComponentSchema refuses the node-level spelling as an unrecognized key, so objectui validate now agrees with os validate. The renderers are untouched. objectql.zod.ts's two public-block arms import the one propsBag helper instead of a byte copy of it; the member's description is unchanged. Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ Co-authored-by: Claude <noreply@anthropic.com>
…n-channel Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
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
Size Limits
|
Contract reviewServed-tier: Inputs, and nothing else: card objectui#10872 (body and all 40 comments, ① Derived judgmentsThe ruling and the fork prohibition (claim
Accept-set changes, each named. On
Nested nodes under the four (the seat's question; dev
The four declared surface widenings, and the parity strings.
The Construct, a nit only. The helper is Check-runs on the head. Read twice while rendering this record: at the first read 42 runs stood at 33 success, 3 expected skips (dependabot, the two coverage matrix rows) and 6 test shards still in progress; at the final read, immediately before this write, all 43 runs are concluded — 40 success, 3 expected skips, 0 failure. Success includes every ② Semver level
The prose, line by line:
③ Boundary flags
Implemented-by: VERDICT: PASS |
Part of #10872
Clause-②: yes
objectui#10872 batch 6: the four
page:containers take their child list inproperties.children.page:card,page:section,page:footerandpage:sidebarnow refuse a node-levelchildrenby name, and restatebodywith the same message. The message's first sentence namesproperties.children, the member each block's@objectstack/specrow declares. Also in this PR, with no behaviour change:objectql.zod.ts's two public-block arms import the onepropsBaghelper instead of keeping a byte copy of it.The card stays open.
record:line_items(no spec row yet) and the rest of the flat-props / envelope-key batch remain, as the claim and release5909279008list them.The ruling this executes, and the premises it rests on
The seat applied triage's
action:*answer (5906817482: "Thepropertiesbag is the contract", "B is not taken … a second dialect") to this branch. The ruling holds only on premises 1–4 of the order, so each was measured before the first edit to the four arms. All four hold for all four containers.origin/maincfc9b6db98, installed@objectstack/spec17.5.0)childrenon all fourPageComponentSchema.safeParse({ type, children: [node] }):unrecognized_keyswith keys["children"]on each of the four. The message reads "Unrecognized key(s) on this page component:children. Before ADR-0089 D3a these were dropped silently…".{ type, properties: { children } }and a bare{ type }both pass. Control:page:tabs,page:headerandrecord:detailsgive the same refusal, so the instrument is live.childreninsidepropertiesComponentPropsMap['page:card']isPageCardProps, with keystitle,bordered,actions,children,body,footer,aria.actionsandbodyare[REMOVED]tombstones, andbody's text says "Rename the key tochildren". The other three rows are allPageContainerProps(identity checked), whose one key ischildren. Everychildrenisz.array(z.unknown())and optional, and each row parses{ children: [node] }.SchemaRenderer,ActionProvider,I18nProviderand the@object-ui/componentsregistry (happy-dom). Each container got twoelement:textmarkers inproperties.children. All four rendered both markers, in order, and the DOM was byte-identical to the node-level spelling. The roots werediv.rounded-lg.border.bg-card(card),section.space-y-4, the separator-led footer andaside.flex.flex-col.gap-4. Control: with no children, the render had 0 markers. The mechanism isSchemaRenderer'spropertieshoist, which copies every bag key excepttype/idonto the node the renderer reads.childrenon the fournode scripts/body-dialect-census.mjs --keys page:card,page:section,page:footer,page:sidebar,page:tabs,page:accordion,grid,flex,card --json. objectui (9440 files): 7 nodes of the four types carry a node-levelchildren, all in thetestbucket (sixpage:sectionand onepage:card, in app-shell render tests). There are 0 inapps/examples/content/docs/skills/packages/*/src. Lit control:cardhas 88 node-levelchildreninexample-appandflexhas 251. objectstack (origin/main72f8c38201,apps/examples/packages/contentarchived into the scratchpad, 8379 files): 109 nodes of the four types (83page:card, 20page:section, 1page:footer, 5page:sidebar), and 0 carry a node-levelchildren. Lit control:flexhas 2. The showcase's ownmy-workpage writespage:cardwithproperties.children, and the spec lint'spage-walksays "PageComponentSchemais.strict(), so a component carries nochildrenkey of its own". Writers read directly: the page designer's canvas addressesproperties.childrenforpage:cardandpage:section(childGroupsinPageBlockCanvas), and for any block that already carries that array. The inspector writes every prop intoproperties(patchProp). The default page synthesizer (buildDefaultPageSchema'scomponentNode) emits{ type, properties }and none of the four types.objectBlockPropsBagis a byte copy ofpropsBagd7a54fe8…) anddiffexits 0. Folded:propsBagis exported frompublic-blocks.zod.tsandobjectql.zod.tsimports it. There is no third copy, and the barrel still does not re-export it.NAMESPACED_REFUSED_AT_TYPEdoes not moveregistered-types-validate-ratchet-10859.test.tsis green in the sweep below.What changed
packages/types/src/zod/public-blocks.zod.tschildrenandbodyasretirementTombstonemembers. Both are fed ONE string from a new local composer,pageContainerChildListGuidance(type, row). This is the objectui#9256 construct with a different message: these blocks do render their child list, so the neither-channel text would be false for them. The first sentence namesproperties.children, the row (PageCardProps/PageContainerProps) and the node to write. The message also says the spec refuses the node-level spelling, and that the hoist makes the move a no-op at render time.propsBagis exported, and its docblock says it is the one copy, internal, and not re-exported fromindex.zod.ts.bodyon the containers is refused by the base's objectui#6771 retirement, "whosechildrenremedy they do render": this diff makes that false.packages/types/src/zod/objectql.zod.ts: theobjectBlockPropsBagcopy is deleted, andobject-metricandobject-master-detail-formbuildpropertieswith the importedpropsBag.packages/types/src/__tests__/container-children-channel-10872.test.ts(new, 102 tests), in four groups:invalid_typeat the key's own path, and a first sentence namingproperties.children, the block, the row and the node to write. Neither the neither-channel text nor the "Did you meanbody→children?" remedy appears. One string feeds.describe()and the issue message, every value is refused, and both keys are members.properties.childrenparses, the bare node parses, the bag spelling parses nested in apagewhile the node-level spelling is refused there atchildren.0.children, andpage:card's full row (title,bordered,children,footer) parses.children, so the remedy names a real member.objectql.zod.tsarms'propertiesdescription is word-for-word the helper's text, from the same composer as thepublic-blocks.zod.tsarms..changeset/10872-container-children-channel.md:'@object-ui/types': minor,Clause-②: yes (narrowing), see below.Surface beyond the order's file list, each forced by this diff and declared
content-channel-public-blocks-9256.test.ts: its "CONTROL —%srenders the node's child list, so it still takeschildren" rows asserted that the four ACCEPT a node-levelchildren, which is the exact behaviour this batch narrows. The control keeps its purpose, which is to show that a reader keeps its channel. It now assertsproperties.childrenparses on the arm and onAnyComponentSchema, and that the node-level refusal is not the neither-channel text. Text of the other rows is untouched.record-alert-flat-body-remedy-10872.test.ts: its "CONTROL arm —page:card… keepsBaseSchema's objectui#6771 refusal" asserted the oldbodymessage onpage:card, which this batch restates. The control moves tocard, which reads the node-levelchildrenand keeps the objectui#6771 remedy. It asserts the same three facts, and a comment records the move.packages/types/src/zod/README.md: one sentence. "Every arm except the fourpage:containers … refuseschildrenandbody" would now misdescribe the four, so it gains a sentence saying they refuse both with a message namingproperties.children. This follows AGENTS.md Add automated testing infrastructure and CI/CD workflows #2, and batch 5's README hunk was ratified on the same ground..changeset/10872-public-block-zod-arms.md(pending, batch 1): a dated note only, with the frontmatter untouched. Its flat-props bullet sayschildrenon the four is "judged against the base's own types", and thatbodyonpage:cardis refused "by the base's objectui#6771 retirement". Neither describes the release as a whole any more. This is the dated-note precedent of batches 2–4 on that same file.zod-mirror-parity.test.ts: the fourEXCLUSIONSreason strings name the new members (text only, the order's allowance).Changeset:
minor, and whymainon four exported arms: a node-levelchildrenis refused where it parsed. HenceClause-②: yes (narrowing).minor, on the objectui#9256 / batch-5 precedent. This repo forbidsmajorin any changeset (onefixedgroup) and spells a narrowing asminorwith an explicit note.@object-ui/types17.6.0 (npmlatest, 2026-08-24) carries no public-block arm: its dist has 0 hits forPageCardBlockSchema/PageSectionBlockSchema/PublicBlockComponentSchema, against 1 each for the controlsCardSchema/FlexSchema. ItssafeValidateSchemaanswersinvalid_unionfor{ type: 'page:section' }, with or without children and with a bag, and forpage:footer/page:sidebar, while the control{ type: 'card', children: [...] }passes. So across the release the accept set only widens.Tests (final head
573373f931,maine6bc087a30merged in; all heavy runs throughos-verify-lock)pnpm --filter '@object-ui/types^...' buildERR_PNPM_RECURSIVE_RUN_NO_SCRIPT. The closure is empty (@object-ui/typeshas no workspace dependency), so nothing ran. Not a red build.pnpm --filter @object-ui/types buildpnpm --filter @object-ui/types type-checktsclegs, andtsconfig.test.json --listFilesOnlylists the three edited or new test filespnpm exec vitest run packages/types/Test Files 290 passed (290),Tests 7012 passed (7012)packages/typeshit ofgit grep -lwonAnyComponentSchema/StrictAnyComponentSchema/PublicBlockComponentSchemain tests (thepackages/typeshits run in the row above), plus the app-shellblock-config-schema-parity-8216oracle,check-handler-key-read-sites.test.tsandregistry-inputs-spec-parity.test.tsTest Files 13 passed (13),Tests 396 passed (396). Includesregistered-types-validate-ratchet-10859.test.ts.The same matrix ran green on
8e2dd4e1edbefore the merge ofmain: 290 files / 6984 tests, and the 13-file sweep with 396 tests.Ablation (proves the pin can fail; nothing permanent left behind).
node /home/user/objectstack/scripts/ablation-replace.mjsran nested four deep in WRAP mode, one leg per arm, each with--deleteof that arm's two member lines. Each leg reported "ok mutation landed", with the anchor count going from 1 to 0. During the mutation,grep -cfor the four constants' tombstone calls read 0. The pin files live inpackages/typesand import the arms by relative source path, so there is nodist/leg.container-children-channel-10872.test.ts (102 tests | 60 failed)andcontent-channel-public-blocks-9256.test.ts (230 tests | 4 failed), which isTests 64 failed | 268 passed (332).git diff HEADis empty", and the outer script's own check read "git diff HEAD empty: yes".Gates (head
573373f931, each exit captured before any pipe)node scripts/check-changeset-presence.mjs: exit 0. "7 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/10872-container-children-channel.md."pnpm changeset:check: exit 0. "No changeset declares amajorbump."check-changeset-overwrite: exit 0, report-only. "1 changeset(s) added, 1 modified, 0 deleted"; the modified one is the dated note, and its frontmatter is unchanged.check:changeset-claims: exit 0, report-only. None of the 32 flagged pending changesets names the four containers or the helper.check:pending-changeset-literals: exit 0.check:control-bytes: exit 0, "OK (scanned 9615 tracked text file(s))". Agrep -naPself-scan over the nine changed files found 0 lines.check:new-line-citations: exit 0, "0 new citation(s)".check:handler-key-reads: exit 0, "OK 139 arm(s) … 57 judged, 0 left unjudged on an arm with an unresolved spread".check:spec-symbols,check:test-path-roots,check:installed-pin-claims,check:doc-types,check:doc-fences,check-doc-links,check-type-check-coverage("43/43 packages compile their tests"),check:unreferenced-sources, andmarkdown-test-inputs.mjs --audit("107 candidate test files, all adjudicated"). This batch adds no markdown reader.--no-inline-config --format jsonover the six changed TS files: 6 files, 0 errors. There are 3 pre-existingno-explicit-anywarnings outside the hunks. Invariance:--print-configshows noparserOptions.project/projectService, so linting is not type-aware and this diff cannot move a verdict on an untouched file. The repo-widepnpm lintis left to CI.check-governed-queue-guard --testover the nine paths: "NOT GOVERNED".check:doc-snippets, reason "PRECONDITION NOT MET (exit 2)". It needs 34 packages built, and the README change is prose outside any fence. Left to CI.check:readme-exports, reason exit 1, "531 self-import(s) could not be judged … the population COLLAPSED". Other packages'distis missing. Left to CI.Serial / overlap
mainmoved while this ran: PR objectui#11207 (app.zod.tsand its pins) and five others landed. None touches a file of this diff.git merge-treewas clean,mainwas merged in (merge, no rebase), and the matrix above was rerun on the merge. The seat named an in-flight branch for objectui#9547 that editsobjectql.zod.ts(itsonNavigateregion) andzod-mirror-parity.test.ts(its own rows). This diff's hunks there are the helper region and the four container rows only.Acceptance notes (not filed; for the seat)
children(andpage:tabs/page:accordionitems[].children) asz.array(z.unknown()). So{ type: 'page:section', properties: { children: [{ type: 'no-such-type-xyz' }] } }parses green on both faces, and so does a malformedelement:textthere. The same child written at node level was refused (invalid_unionatchildren). The spec's lint walks those bag arrays by hand (page-walk), soos validatestill judges them. What this batch moves is only which spelling is accepted, not whether nested content is judged by the publish gate. The pre-existing gap belongs in its own card. Dedupe words:properties.children nested node not validated·bag slot children z.array(z.unknown()) objectui validate·items[].children unjudged safeValidateSchema.@object-ui/sdui-parser'sBASE_PROPSlistschildren, andisContainerauthorises it on the four, so the manifest tier and the VS Code validator pass a node-levelchildrenthat both zod faces now refuse. This is batch 3'srecord:alertpattern. The carrier is this card's flat-props / envelope-key batch, whose order names both tiers. ⛔ Not touched here: the order excludespackages/sdui-parserandpackages/vscode-extension.@object-ui/reactand@object-ui/componentsin a DOM project, but@object-ui/typesimports no renderer and its tests run in theunit(node) project. Its home would bepackages/components/src/__tests__/, which is outside the claimed surface. The probe's readings are in premise 3 above. If the seat wants it pinned, a follow-up with that surface is a small test.skills/objectui/guides/page-builder.mdsays the three thin containers "render asection,footerandasidearound theirchildren". That is prose, true at runtime, and names no node spelling. It is governed, so it is only noted here.Generated by Claude Code