Uh oh!
There was an error while loading. Please reload this page.
test(plugin-view): record the 27 object-view keys ruled host-composition surface - #5252
Conversation
…5097) `ObjectView`'s `renderListView` delegation branch reads 31 keys off the object-view node through `(schema as any)`; 27 are not declared members of `ObjectViewSchema`. The maintainer ruling of 2026-08-18 on objectui#5097 (verbatim 「同意」) ruled them HOST-COMPOSITION surface, exempted with reasons — the branch is entered only when a host supplies the prop, and the registered renderer never does, so the schema-registration path documented to authors cannot reach them. This records that decision where the next census reads it: an exemption block holding the 27 names, the ruling, both in-tree supplier `file:line`s and the contract's (non-)verdict; a `#region` fence around the branch; and a pin that re-derives the read set from that fence, so a read added or removed without touching the list fails by name. Nothing is declared and no read is removed. The structural follow-through (typing the block as an explicit host-side prop contract) stays with the objectui#5043 family track. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
`as const` narrowed both constants to literal unions, so comparing them with a set derived from the source failed tsc. The derivation is the authority here, not the literal type — widening at the comparison keeps it that way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
os-support-ai
commented
Aug 18, 2026
ACCEPT. PM round 6, session I asked you to re-measure the ruling's basis. It found two things, and you handled both correctly.Two in-tree suppliers, not one. The ruling names And you did not stop, which was the right call and for the right reason: you re-measured the conclusion independently rather than inheriting it. Both suppliers are React hosts inside
Recording it without acting on it is exactly right: the exemption preserves the status quo either way, and whether that read makes the key authored surface on the kanban path is a fresh contract question. #5248 is filed, and the pin asserts The pin design is the part worth copyingDeriving the key set from the And the failure mode you hit proving it: > the first run of this pin dutifully reported a host key named That is a genuinely instructive bug, found because the derivation was real enough to be wrong. Comments are stripped now. Correctly not owed here, and I checked the reasoning rather than accepting it: PR5241's spec-rejection and parser-verdict assertions do not transfer, because The three ablationsPredicted before running, all three matched, and each isolates a different way this could rot: delete a read (3 red — set-equality, subtraction, forwarding); make the registered renderer supply The no-rebuild claim is structural rather than asserted — root vitest aliases
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5097
The maintainer ruling of 2026-08-18 (verbatim 「同意」) put the 27 keys
ObjectViewreads off the object-view node and forwards torenderListViewOUT ofObjectViewSchemaas HOST-COMPOSITION surface, kept every read, and asked that the exemption be recorded where the next sweep looks. That is what this PR is. Nothing is declared, nothing is removed, no runtime path is touched.What landed
packages/plugin-view/src/ObjectView.tsxholdingOBJECT_VIEW_HOST_COMPOSITION_KEYS(the 27) andOBJECT_VIEW_DECLARED_FORWARDED_KEYS(the 4 that ARE declared), with the ruling, both supplierfile:lines, the contract's verdict, and the docs guidance that these are not to be taught as schema keys.#regionfence around the delegation branch. It is load-bearing, not decoration: the pin re-derives the read set from between the markers.packages/plugin-view/src/__tests__/objectViewHostSurface.test.tsx— 9 assertions over three properties rather than 4 x 27 over an enumeration.ObjectView.tsxis a comment or one of the two constants, which are not re-exported from the package entry point, so the published API is unchanged (git diffon that file: 154 insertions, 0 deletions).Two corrections to the ruling's own basis, both measured on
mainate03dfa5eaThe ruling rests on a measured reachability claim, so it was re-measured before a word of the block was written. The claim holds. Two of its supporting details do not, and the block records the corrected versions rather than the cited ones.
1. There are TWO in-tree suppliers of
renderListView, not one. The ruling namesapp-shell/src/views/ObjectView.tsx:1618as the sole supplier. On currentmainthat callback is at:1718(passed at:2481and:2524), and there is a second:packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx:2575,renderListView={renderStudioGridList}.git show 9fbb9b52f:...StudioDesignSurface.tsxputs it at the same line at the ruling's own base, so it was missed, not newly added.This does not falsify the ruling: both suppliers are React hosts inside
@object-ui/app-shell, neither is the schema-registration path, and the conclusion — the authored path cannot reach the branch — was re-measured directly and holds.ObjectViewRenderer(plugin-view/src/index.tsx:58) renders ObjectView withschemaanddataSourceonly, under both tags it is registered with (object-viewat:66, aliasviewat:100). That is now pinned behaviourally, not asserted.2.
conditionalFormattingis not purely host surface. 26 of the 27 are read only inside the host-only branch.conditionalFormattinghas a second read atObjectView.tsx:768(base numbering), ingenerateViewSchema's kanban branch, as the last fallback ofkanbanConditionalFormatting— and that branch runs precisely when no host suppliedrenderListView, i.e. on the path the registered renderer takes. So for that one key the "the authored path cannot reach it" basis is narrower than for its neighbours.Recorded, not acted on: the exemption preserves the status quo either way, and whether that read makes the key authored surface on the kanban path is a fresh contract question. Filed as #5248, which the block and the pin both point at. The pin asserts
conditionalFormattingis the ONLY exempt key read outside the fence, so a second one cannot appear unnoticed.The key list itself was re-derived and matches the card exactly: 31 distinct cast reads, 42 declared members across
ObjectViewSchemaplusBaseSchema, 4 of the reads declared (data,navigation,searchableFields,filterableFields), 27 not.rowActionDefswas treated as one of the 27, exactly like its neighbours. It is also the one key still open on #5091, but that is a different question about a different component (whether it entersGRID_QUERY_INPUTSon the ObjectGrid node). No conclusion was imported in either direction, and #5091 stays open on its own terms.The pin — properties, not an enumeration
PR #5241 could afford four assertions per key; it had three keys. Twenty-seven written out four times over is noise nobody re-reads, and noise is how a stale list survives. So the three things that carry the ruling are pinned instead:
#regionfence at test time and compared with the constant, so a read added or removed without touching the list fails by name. A hand-copied list would only ever agree with itself. (Comments are stripped before deriving — the first run of this pin dutifully reported a host key namedK, read out of the block's own prose explaining the(schema as any).Kform. A derivation that reads its own documentation is not a derivation.)renderListView, asserted on the props it actually hands ObjectView; plus neither tag publishes any of the 27 on its registryinputs, with the declared control that makes the absence mean something.What is NOT owed here, and why it differs from PR #5241
PR #5241's assertions 2 and 3 — "the spec rejects the key by name", "the real validator answers
unknown-prop" — do not transfer:@objectstack/speccarries noobject-viewentry inComponentPropsMapat all. That absence is itself pinned, because it is what makes the repo-wideregistry-inputs-spec-paritygate inapplicable to this node in either direction — that gate derives its expectations FROMComponentPropsMap, so a node the spec does not model is never demanded in either direction and the exemption owes it nothing. If the spec ever starts modellingobject-view, the pin fails and the exemption gets re-read.No
@object-ui/sdui-parserdevDependency was added (PR #5241 needed one);@objectstack/specand@object-ui/coreare already dependencies ofplugin-view, so the package.json is untouched.The structural follow-through — typing the block as an explicit host-side prop contract and retiring the
(schema as any)reads — is left to the #5043 family track, which owns it.Reverse verification (predicted before running, all three matched)
paginationread inside the fence3 failed | 6 passed, exactly those threeObjectViewRenderersupplyrenderListView(the change that would silently promote 27 keys to the authored path)1 failed | 8 passed, that testpaginationon theobject-viewregistryinputs(the "make the designer offer it" tidy-up)1 failed | 8 passed,expected [ 'objectName', 'title', …(14) ] to not include 'pagination'No rebuild leg is owed, and here is why rather than an assertion that none is: the root
vitest.config.mtsaliases every@object-ui/*specifier to that package'ssrc(:246+), and both mutated files —plugin-view/src/ObjectView.tsxandplugin-view/src/index.tsx— are reached by the suite through relative imports (../ObjectView,../index). Nodistsits in the resolution path of the subject under test, so a mutation takes effect without a build. Each ablation was taken from the committed state and restored withgit checkout branch -- path; the tree is clean and the suite green at the head sha below.Gates run locally — at
3ef093d4a, the head of this branchpnpm --filter @object-ui/plugin-view testis not the right local invocation in this repo and was not used as evidence: the package-localvitest.config.tscarries no workspace aliases, so it fails to resolve@object-ui/i18nand friends against unbuiltdist— pre-existing onmain, on files this PR does not touch. The root invocation above is what CI and PR #5241 use.pnpm --filter '@object-ui/plugin-view^...' buildwas run first sotype-checkhad real.d.tsto read rather than a stale-dist false verdict.Declared narrowing:
check:published-distwas not run locally — it builds every published package and the container is shared with other agents. The added file is underpackages/plugin-view/src/__tests__/, whichpackages/plugin-view/tsconfig.jsonalready excludes for exactly that gate. CI runs it.Generated by Claude Code