Repository navigation
fix(types): the six held public blocks refuse the content channels no renderer reads (objectui#10872 batch 5) - #11193
Conversation
… renderer reads (objectui#10872 batch 5) `action:button`, `action:icon`, `action:group`, `action:menu`, `element:definition-list` and `element:repeater` took `BaseSchema`'s channels as they were when batch 4 armed them: a node-level `children` parsed green on both faces and rendered nothing, and a flat `body` was refused with a remedy naming `children`. Each arm now declares `children` as a by-name refusal and restates `body` with the same guidance (the objectui#9256 construct, unchanged: `retirementTombstone` fed one `neitherContentChannelGuidance` string). The message names the block's real content channel inside `properties` (`actions`, `items`, the label and icon) and says so where there is none (`element:repeater`). The spec's own page component refuses the same key. Pinned by held-block-content-channels-10872.test.ts, on both faces. Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ Co-authored-by: Claude <noreply@anthropic.com>
…six arms' channel refusals (objectui#10872 batch 5) The zod-mirror-parity EXCLUSIONS rows of the six batch-4 arms, and the zod README paragraph on them, said the arms carry no content-channel refusal; both now describe the refusals batch 5 adds. The changeset declares the narrowing (`minor`, Clause-②: yes) and records why it breaks no published document: the six arms are unreleased, and in `@object-ui/types` 17.6.0 every node of these types is refused at `type`. Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ Co-authored-by: Claude <noreply@anthropic.com>
…tui#10872) `tsc -p tsconfig.test.json` lost the tuple element types through a spread of `slice(1)`; the cases are now built by destructuring. 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: PR objectui#11193 (draft, ① Derived judgmentsEach accept-set or public-surface change the diff implies, with a verdict.
② Semver level
③ Boundary flagsEvery dev flag (PR body "Deviations" and report
Dev "NOT MEASURED":
Acceptance note / out-of-scope finding (carrier: this card's flat-props / envelope-key batch): the spec's Zone 2 assumptions (five, each measured by the dev): every one I could re-read from source holds (①1–3). The runtime probe and the TypeScript census are one-off and uncommitted; the committed pin records the validator's answer, not the renderers', and says so — the objectui#9256 shape. In-flight overlap, re-read against the claim's serial line: PR objectui#11125 shares Check-runs on PR state: draft, Implemented-by: VERDICT: PASS |
Part of #10872
Clause-②: yes
Batch 5 of objectui#10872: the content-channel narrowing of the six held public blocks, by the objectui#9256 method. The blocks are
action:button,action:icon,action:group,action:menu,element:definition-listandelement:repeater, the six arms batch 4 armed by reference (PR objectui#11180). The card stays open for the rest of its remainder:record:line_items, which has no spec row, and the flat-props / envelope-key batch.The defect
Batch 4 gave each of these blocks an arm, and each arm took
BaseSchema's channels as they were.{ "type": "action:group", "children": [ … ] }parsed green on both faces:safeValidateSchema(whichobjectui validateruns) andStrictAnyComponentSchema. The same held on all six.childrenorbody, andSchemaRendererstrips both keys out of the props it spreads. So the child list rendered nothing, and nothing warned at render time.bodywas already refused (objectui#6771). Its message said "Did you meanbody→children", which pointed the author at the key that did nothing.The change
packages/types/src/zod/public-blocks.zod.ts, the six arms only. Each arm declareschildrenas a by-name refusal and restatesbodywith the same guidance. That is tworetirementTombstonemembers fed oneneitherContentChannelGuidancestring, both kept members: the construct the nineteen objectui#9256 arms already use. There is no new helper and no copy of one. The message names what the block renders instead, which is where the content goes:properties.actionsforaction:groupandaction:menu;properties.itemsforelement:definition-list;properties.labelandproperties.iconfor the two buttons, whose label and icon are their whole content;element:repeater, which has no content channel. Its message says so.The module docblock's "The content channels" section is updated to match: its paragraph said these six carry no channel refusal.
packages/types/src/__tests__/held-block-content-channels-10872.test.ts(new, 115 tests). It covers both faces:invalid_typeat its own path;.describe()metadata;propertiesnode parses on both faces;page, the block parses without a child list and is refused with one;PageComponentSchemarefuses a node-levelchildrenon each of the six (see below).Two text follow-ons that the arms made false (see Deviations). In
zod-mirror-parity.test.ts, the sixEXCLUSIONSreason strings and their comment said "minus the objectui#9256 channel refusals". The matching paragraph inpackages/types/src/zod/README.mdsaid "They carry no content-channel refusal"..changeset/10872-held-block-content-channels.md. It declares'@object-ui/types': minor(below).Zone 2: the PM's mechanism assumptions, each measured
childrenon the six: CONFIRMED, by a runtime probe per block. This is a one-off probe and was not committed. It ran the realSchemaRendereragainst the real registry. Each registered renderer was wrapped so that theschemait receives is a Proxy logging everyget/has/getOwnPropertyDescriptorofchildrenandbody. Each node was rendered without, and then with, a marker child (element:text).action:groupdropdown andaction:menuopened: their items were visible),action:groupinline, an empty definition list, and a repeater painting two rows from an adapter.page:cardwith the same child rendered the marker, and its wrapper logged 4 reads. The instrument sees a reader when one exists.bodyleg gave the same result: 0 reads, identical DOM.not-a-containerwarning (objectui#9910) fires on all six.page:carddraws none.@object-ui/components, where all six register, on a built tree: the workspace dependencies resolved todist/index.d.ts, with 0 diagnostics in the closure. It listed every.children/.bodyread in the in-package import closure of the modules that register the six (64 files). That came to 29 reads, all insrc/ui/*Shadcn primitives, each destructuring Reactchildrenfrom a Radix or HTML props type. There were 0 reads in the six renderers' modules,readPropsor the action helpers.action:*renderers, adds no read of either key. Its added lines were grepped on its head05d9cfdfa, and thebodyhits there are fetch request bodies in tests.children: it REFUSES it. On@objectstack/spec17.5.0,PageComponentSchema.safeParse({ type, id, children })returnsunrecognized_keysnamingchildrenfor each of the six, with the message "Unrecognized key(s) on this page component:children. Before ADR-0089 D3a these were dropped silently …". The same node withoutchildrenpasses. The spec's page component has no node-levelchildrenat all. So this is not a second dialect: the tombstones bring objectui's face into line with the spec. The new pin's last block re-reads this from the installed spec, so a spec that starts accepting the key turns red there.childrenorbody.action:groupandaction:menu: the channel isactions.element:definition-list: the channel isitems.action:buttonandaction:icon: no child channel. Their content is thelabelandiconmembers, and the message names those.element:repeater: no content channel. Its rows printtitleField/fieldsvalues of the queried record, with no template or slot, and its message says so.BaseSchema.extend({ type, properties: propsBag(…) }), the same shape as the nineteen objectui#9256 arms. The same two helpers apply unchanged.neitherContentChannelGuidance's fixed sentence states a TypeScript type-checker measurement, aSchemaRendererstrip and anot-a-containerwarning. Each of those was measured true for the six, as recorded in item 1.NAMESPACED_REFUSED_AT_TYPEdoes not move: CONFIRMED.git diff 37d1662 -- packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.tsis empty, and that test is green at head. No type joins or leaves refused-at-type. Draft PR objectui#11069's hunks are untouched, and that PR shares no file with this one.Semver:
minor, and why nothing published breaksminorfollows the objectui#9256 narrowing precedent: this repo's version policy forbidsmajorin any changeset. But the narrowing is not breaking against the last release, and that was measured:npm view @object-ui/typesgiveslatest=17.6.0, the same aspackages/types/package.json.distcarries noActionButtonBlockSchemaand noaction:buttonliteral.safeValidateSchemarefuses every one of the six types, with and withoutchildren, withinvalid_unionattype. Apagepasses as a control..changeset/, so batch 4 and this batch ship in one release. Across that release the accept set only widens.This refines the claim's
Clause-②reason ("narrows the published accept set").Clause-②: yesis kept as the claim directs.Tests and gates, at head
79b4668ae(clean tree), with exit codes captured before any pipeos-verify-lockchain:pnpm --filter @object-ui/types buildgives "✓ dist completeness: 1 package(s) complete (136 emitted files verified)".pnpm exec vitest run packages/types/gives "Test Files 286 passed (286) / Tests 6726 passed (6726)".pnpm exec vitest runover five files gives "Test Files 5 passed (5) / Tests 321 passed (321)". The files arepackages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts,scripts/__tests__/check-handler-key-read-sites.test.ts,examples/schema-catalog/test/safe-validate-corpus-6318.test.ts,apps/console/src/__tests__/registry-inputs-spec-parity.test.tsandpackages/cli/src/__tests__/validate-union-arm-selection.test.ts.pnpm --filter @object-ui/types type-checkrunstsc --noEmit,tsconfig.examples.jsonandtsconfig.test.json.tsc -p tsconfig.test.json --listFilesOnlylists the new pin, and the chain ends withVERDICT command-exit 0.pnpm --filter '@object-ui/types^...' buildstep the order names selects an empty closure, because@object-ui/typeshas no workspace dependency. pnpm answersERR_PNPM_RECURSIVE_RUN_NO_SCRIPT(exit 1): nothing ran, and that is not a red build.node scripts/check-changeset-presence.mjs: "4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)";pnpm check:control-bytes: OK, 9549 files;pnpm check:new-line-citations: "0 new citation(s)";pnpm check:handler-key-reads: "OK 139 arm(s) … 57 judged";pnpm check:changeset-claims;pnpm check:pending-changeset-literals;node scripts/check-changeset-no-major.mjs;node scripts/check-changeset-overwrite.mjs;pnpm check:installed-pin-claims;pnpm check:spec-symbols;pnpm check:test-path-roots;pnpm check:doc-types;pnpm check:doc-fences;node scripts/check-doc-links.mjs;node scripts/check-type-check-coverage.mjs: "43/43 packages compile their tests";node scripts/markdown-test-inputs.mjs --audit: "107 candidate test files, all adjudicated". This batch adds no markdown reader.pnpm exec eslint --no-inline-config --format jsonon the three changed TS files counted 3 files, 0 errors and 2 warnings. Both warnings areno-explicit-anyinzod-mirror-parity.test.ts, already there and outside this diff's hunks..tsfiles in the diff. The other two changed files are markdown.eslint --print-configshows noparserOptions.projectand noprojectService, so linting is not type-aware and this diff cannot move a verdict on an untouched file.pnpm lintis declared to CI.Ablation (one-off, trap-guarded, via
ablation-replace.mjsin objectstack): the whole six-arm region at HEAD (12954 bytes) was replaced by the same region at base37d1662(6196 bytes), which is exactly the batch-4 arms.370bd3e00e51→da78bcf5a4f5.childrenrefusals;childrencases;BaseSchemadeclares both keys), the positive controls, the spec block and thebodyrefusal code.git diff HEADis empty".distleg applies.NOT MEASURED:
check:doc-snippets: PRECONDITION NOT MET (exit 2). It needs 34 packages built. This diff edits no fenced block: the two changed lines ofpackages/types/src/zod/README.mdare prose paragraphs outside any fence, so they cannot move that gate's verdict. Declared to CI.check:readme-exports: exit 1, "431 self-import(s) could not be judged", every one because another package'sdistis not on disk. It reports 0 findings underpackages/types(built) and "0 wrong-path, 0 fabricated". Declared to CI.In-flight overlap, re-read at this head
8f9bb76f6) shareszod-mirror-parity.test.ts.git merge-tree --write-treeof this branch with its head exits 0.05d9cfdfa) shares no file with this PR, and adds no channel read (Zone 2, item 1).a11f73347) shares no file with this PR. Its strict-face wiring agrees with this change, because both faces refuse.Deviations (declared)
packages/types/src/zod/README.md, one paragraph and one sentence. They stated the opposite of this change: that these six carry no content-channel refusal. AGENTS.md Add automated testing infrastructure and CI/CD workflows #2 requires a package README to follow the code, and batch 4's claim amendment ratified the same README paragraph as an additive fix. The file is not in this claim's file surface. It sits in commitb4be1d8together with the census rows and the changeset, so dropping it means reverting that file's hunk, not the commit.zod-mirror-parity.test.ts: only the six rows this batch moves, plus their comment. Text only: the census reads reasons for presence and length, not for content.Acceptance notes
PageComponentSchemaalso refuses a node-levelchildrenon the fourpage:containers (page:cardwas measured in the same probe:unrecognized_keys,children). objectui accepts one there, and its renderer does read it. That is the node-level spelling of a spec container'sproperties.children, the same class as the flat keys that batch holds, and it is not this batch's to decide.Governed surfaces: none. This PR does not touch any governed surface:
node scripts/check-governed-queue-guard.mjs --testreports "NOT GOVERNED — 5 path(s) checked".Implemented in session
https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ.Generated by Claude Code