Repository navigation
fix(components): a page:tabs item visibleWhen that faults withholds its tab (objectui#13286) - #13297
Merged
objectstack-fleet[bot] merged 2 commits intoOct 21, 2026
Conversation
…ts tab (objectui#13286) A declared item predicate that cannot be evaluated (over the CEL AST bound, a type error, an unbound root, a missing function) used to fall back to visible, drawing the tab for a viewer the predicate was written to exclude. It now fails closed, read off the single engine call's onFault, and is reported once per source through the shared reporter with the withholding consequence. Absent and blank predicates still mean visible; form field rules keep their documented fail-open. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
… pin Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
Contributor
✅ 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
|
objectstack-fleet
Bot
deleted the
claude/issue-13286-page-predicate-fail-closed
branch
October 21, 2026 04:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #13286
Clause-②: no
What changed
A
page:tabsitemvisibleWhenthat faults on evaluation now fails closed: the tab (header and panel) is withheld instead of drawn. Faults covered: a source over the CEL engine's AST bound ([bounds] Exceeded maxAstNodes), a type error, an unbound root, a missing function, a malformed source, and a declared value that cannot be evaluated at all.PageTabsRenderer.isItemVisible(packages/components/src/renderers/layout/containers.tsx) still makes ONEevaluateConditioncall. It reads the fault off that call'sonFaultand overrides the evaluator's fail-softtrue. It does not usethrowOnError, which would evaluate a CEL envelope twice.visibleWhenstill means visible. A blank one ('', whitespace, an empty-sourceenvelope, i.e.hasDeclaredPredicatefalse) still means "no gate". It is visible and diagnosed with[blank]as before.reportUnresolvableVisibilityPredicate, with the same dedupeSetkeyed on (node type, key, source). It now passes the'withholding'gate kind, the reporter's fail-closed visibility copy, so the console line says the tab was WITHHELD. It no longer says "the gate did NOT bite".falsepredicate takes (the filtereditemsfeedingactiveValue), and pin (e) measures it.content/docs/guide/metadata-diagnostics.md: the paragraph that said every node gate in this family keeps its verdict now names thepage:tabsitem gate as the one that fails closed. Without that edit the sentence would be false after this change.Sites changed and sites left
page:tabsitemvisibleWhen(isItemVisible)page:tabscount-probe gates (isGateOpen)visibleWhen/visible/visibleOninSchemaRenderer(packages/react)page:headeractionvisible/disabledpage:headeractionhiddenresolveFieldRuleState/evalFieldPredicate), form sections and field-group tabsTests
New
packages/components/src/__tests__/page-tabs-visible-when-fail-closed-13286.test.tsx:falsehides,trueshows, absent shows, blank shows, and none of them is reported as withheld;[bounds]reason, while the same shape at 4 terms evaluates and shows;visibleWhenfaults is still drawn;Updated
page-tabs-visible-when-fault-warning.test.tsx: its two cases asserted the old fail-open draw. They now assert the tab is withheld, and their report assertions are unchanged.Runs, at head
c40f99849c:page-tabs-visibility.test.tsx:Test Files 3 passed (3),Tests 20 passed (20);page-tabs-*/pageTabs*test, plus each test that namescontainers.tsx, across components, react, app-shell, plugin-grid, types, scripts and console):Test Files 34 passed (34),Tests 791 passed (791), on the first commit;pnpm --filter @object-ui/components type-check(tsc --noEmit && tsc -p tsconfig.test.json; the second program includessrc/**/*.test.tsx): exit 0, afterpnpm --filter '@object-ui/components^...' buildexit 0.The full
packages/componentsdirectory, and the rest ofpnpm test, are left to CI.Ablation: restoring the fail-open return (
return declared && faulted ? false : verdict;replaced byreturn verdict;throughablation-replace.mjs; the anchor count went 1 to 0) turned (a) x2, (c) and (e) RED (Tests 4 failed | 2 passed (6)). The controls (b) and (d) stayed green. The restore is proven by blob hash: HEAD blob2067d62d9a2dwas mutated to6e32bd0b1c7band restored to2067d62d9a2d, andgit diff HEADis empty. Nodist/step applies: the test reachescontainers.tsxthrough a relative source import (import '../renderers').Gates (exit codes):
check:phantom-deps0,check:self-import0,check:unreferenced-sources0,check:doc-example-readers0,check:handler-key-reads0,check:side-effects-array0,check:element-data-source-declaration0,check:spec-symbols0,check:action-forward-parity0,check:designer-field-key-parity0,check:icon-record-names0,check:i18n-keys0,check:i18n-drift0,check:i18n-designer-parity0,check:control-bytes0,check:doc-types0,check:new-line-citations0,scripts/check-hand-rolled-comment-mask.mjs0,scripts/check-changeset-fixed.mjs0,scripts/check-changeset-presence.mjs0.check:spec-floorsexits 1 because it needs a whole-workspace build artifact (no-artifact), so it is NOT MEASURED here.Lint, narrowed to the 3 changed source files with the package's own
eslint .config:--format jsoncounts 3 files and 0 errors. With--no-inline-configthere is 1 error, at the existingreact-hooks/static-componentssite whose inline disable that flag ignores; it is not on a changed line. Type-aware linting is not configured ineslint.config.js(noparserOptions.project), so this diff cannot move a verdict in any untouched file.Acceptance notes
'withholding'copy names "a navigation entry". A tab strip is in-page navigation, so the sentence is true here. A surface-neutral wording would need an edit topackages/react/src/utils/visibilityDiagnostic.ts, which is outside this claim. Carrier: none.Session:
https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gBGenerated by Claude Code