Uh oh!
There was an error while loading. Please reload this page.
fix(plugin-view): a top-level conditionalFormatting no longer reaches the kanban view (#5248) - #5336
Conversation
… the kanban view (#5248) The kanban branch of `generateViewSchema` resolved its rule list from three links: `options.kanban.conditionalFormatting`, the active view's own rule, then `(schema as any).conditionalFormatting` off the object-view node. Only the first two are declared surface — `ObjectViewSchema` has no such member and the `object-view` registration does not publish it in `inputs` — yet the third was honoured, on the path the REGISTERED renderer takes. It was the one counter-example to the objectui#5097 host-composition exemption, whose stated basis is that its 27 keys are reachable only through the host-supplied `renderListView` delegation. Maintainer ruling 2026-08-19 on #5248 (verbatim 「全部接受」): Option 2, gated on a liveness check, with Option 1 (declare the key) pre-ruled for real authored usage. The liveness check came back empty — no authored document in either repo puts `conditionalFormatting` on an object-view node — so the fallback read is dropped and the exemption's basis now holds for all 27 keys. The host delegation is NOT narrowed: it still reads the key off the object-view node and forwards it, so stored app-shell documents keep rendering. Both halves are pinned by a new test, and the host-surface pin now asserts that zero exempt keys are read outside the fence. 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 19, 2026
ACCEPT — PM review, round 17.
The liveness check is the card, and this one is a reading rather than an absenceThe ruling predicted the empty result and called it "(expected)". A prediction is not evidence, and this was treated as something to falsify. Every zero is paired with a control on the same corpus through the same method:
And a structural cross-check that a keyword sweep alone could not give: no file in either repo carries both an That is what makes the deletion defensible six months from now, which is the point of the artifact being amended. VerificationReverse-verification predicted 4 red and named them before running — two in the new file, two in the pin — and observed exactly The build-artifact question was answered rather than assumed: the repo-root vitest config aliases every The Merging via the queue. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5248
Branch fired: Option 2. The liveness check that gates the 2026-08-19 ruling came back empty — no authored document in either repo puts
conditionalFormattingon anobject-viewnode — so the(schema as any).conditionalFormattingfallback ingenerateViewSchema's kanban branch is dropped rather than the key declared. Theobject-viewnode's 27 host-composition keys (objectui#5097) are now read only inside the#regionfence, so that exemption's stated basis — "reachable only via the host-suppliedrenderListViewdelegation" — is true for all 27 without exception. Option 1 (declare the key onObjectViewSchema+ registryinputs) was pre-ruled for the other outcome and did not fire; Option 3 was explicitly rejected by the ruling and is not implemented.Clause-②:
no. This branch narrows — a key stops being honoured on the author path, restoringdeclared = enforced. It does not widen the accepted set. (Option 1 would have beenyes; it did not fire.)The liveness check — commands and output
The ruling's "(expected)" about an empty result is a prediction, so it was treated as something to falsify. Every zero below is paired with a counter-probe run through the same method on the same corpus with a term known to be present.
objectui — authored corpora (
content/docs,skills,examples,apps):Two files, and neither is the case that fires the fallback: the first documents
object-grid's declared key, the second authors it on alist-viewnode ({ "type": "list-view", "objectName": "invoice", "conditionalFormatting": [...] }) — also declared. Zero top-level occurrences on anobject-viewnode.Controls, same method, same corpora:
object-view→ 5 files (docs 3, examples 1, apps 1);groupByField→ 1 file. Non-zero, so the probe reaches these trees.objectui — remaining dirs (
e2e,scripts,public,docs): one hit,docs/audits/2026-07-objectview-detailview-schema.md:92, prose listing the forwarded keys. ControlobjectNamein the same dirs → 13 files.objectstack (the sibling repo where the real metadata apps live):
The one real authored use,
field-zoo.view.ts:61, sits insidedefineView({ list: { type: 'grid', … } })— a view-level rule on a grid view. That is theactiveView?.conditionalFormattinglink, which this PR keeps.More decisively, an
object-viewnode is not authored in objectstack at all:Controls in that same corpus:
object-form→ 54 files,object-grid→ 19 files. So the zero is a reading, not an artefact of the method.Structural cross-check — every file in either repo containing both an
object-viewmention andconditionalFormatting:packages/types/src/objectql.tsand.../zod/objectql.zod.ts(declarations),plugin-view/src/ObjectView.tsx+ its pin test (the code under change),app-shell/src/views/ObjectView.tsx,ROADMAP.mdand one audit doc (prose), plus objectstack'spackages/spec/liveness/view.json. The app-shell one is the host: it builds itsobject-viewnode atObjectView.tsx:2154without the key, and readsconditionalFormattingat:1962into the delegatedlist-viewnode inside itsrenderListViewcallback. Nothing authored relies on the top-level read.Supporting facts re-measured on this base:
conditionalFormattingis not a member ofObjectViewSchema(0 hits inside the interface inpackages/types/src/objectql.ts), and it is not among the 15 names in theobject-viewregistryinputs(packages/plugin-view/src/index.tsx).What changed
packages/plugin-view/src/ObjectView.tsx— the kanban branch's chain loses its third link. It is nowkanbanCfg.conditionalFormatting ?? activeView?.conditionalFormatting; the comment records the ruling, the liveness evidence and why the fallback must not come back.OBJECT_VIEW_HOST_COMPOSITION_KEYSblock's "The one asymmetry" section is rewritten as "RESOLVED (objectui#5248)", carrying the liveness evidence, and the#regionbanner is updated to match.packages/plugin-view/src/__tests__/objectViewHostSurface.test.tsx— the pin that read.toEqual(['conditionalFormatting'])now asserts.toEqual([]): zero exempt keys read outside the fence. A second, named test pins the same fact for this key specifically, plus its continued read inside the fence.packages/plugin-view/src/__tests__/ObjectView.kanbanConditionalFormatting.test.tsx— new; 7 tests.@object-ui/plugin-viewminor(behaviour change, described as one; nevermajorper the repo's version-alignment rule).Not narrowed: the host
renderListViewdelegation still reads the key off theobject-viewnode and forwards it to the host's list renderer. It stays host-composition surface; a stored app-shell document that carries it keeps rendering. That half is asserted in the new test file so the two cannot drift apart.Tests — measured at
6325ef257New behaviour pinned (all 7 green): a top-level rule does not reach the emitted
object-kanbannode (no own property,undefined); the view-level rule still does; the nestedoptions.kanbanrule still does and still wins; a top-level key neither displaces the declared links nor fills in for a view that declares none; a control thatgroupBy/groupField/titleField/cardFieldsstill flow (without it, "emits nothing" would pass too); and the hostrenderListViewdelegation still receives the top-level key on alist-viewnode.Reverse verification — predicted before running, then observed
Legs: restore
ObjectView.tsxtoorigin/main, keep both test files; then restore to the commit.Build artifact between the edit and the thing under test: none, on either leg. The repo-root vitest config aliases every
@object-ui/*specifier straight atpackages/*/src(vitest.config.mtslines 244-285, including@object-ui/core,@object-ui/types,@object-ui/react), no package in this worktree has adist/at test time, and the edited file lives in the package under test and is imported relatively. The pin test additionally readsObjectView.tsxfrom disk at import. So no rebuild is owed on either leg — and the red leg landing exactly where predicted is itself the proof that the mutation reached the tests rather than a stale artefact.Predicted red (4): the new file's "a TOP-LEVEL rule … does not reach the kanban node" and "a top-level key does not fill in for a view that declares none"; the pin's "NO exempt key is read outside the fence" and "
conditionalFormattingin particular is no longer read outside the fence". Predicted green: the other 13.Observed — identical, no surprises:
Restoration leg (source back at the commit, tests untouched):
Test Files 2 passed (2) / Tests 17 passed (17).Generated by Claude Code