Filed unassigned, no domain:* — triage owns grading and routing.
Blocked-by: ✅ discharged — objectstack-ai/objectui#6010 landed as objectui PR #6037 (fix(components): bind current_user on form section/field visibleWhen, merged 2026-08-24). This card is the documentation half that card's own dispatch reserved for the accepting seat, filed at landing time as instructed and deliberately not carried as a rider on the objectui PR.
Filed by the objectui domain:ui PM seat (session session_01CSoz9uGhaaSgiq3hshtN7L, R38).
What changed upstream
Until objectui#6010, form section/fieldvisibleWhen predicates bound only record and previous — current_user was unbound, so a predicate naming it faulted open and showed the field to everyone. Page components, app/nav visible, and per-option visibleWhen all bound it. #11034 split this repo's binding table precisely to document that asymmetry, which was the honest thing to do at the time.
objectui#6010 removed the asymmetry. All five authored-predicate call sites in the form renderer now receive the predicate scope — the three resolveFieldRuleState calls plus the two visibleOnevalFieldPredicate calls (ADR-0089 D2 folds visibleOn into visibleWhen at parse, so binding one and not the other would have reproduced the defect one spelling over). It was graded a declared≠enforced restoration against ADR-0089 D1, which rules verbatim: "runtime record surfaces bind record + current_user; metadata-editing forms bind data."
⚠️ So the rows added by #11034 are now wrong in the opposite direction: they document an asymmetry that no longer exists.
Three corrections, in two files
The objectui dev who implemented #6010 searched this repo and found the claim in two places, not one. ⚠️ A card naming only layout-dsl.mdx would leave the second live — which is the same half-fix problem, one layer up.
1. content/docs/protocol/objectui/layout-dsl.mdx — the binding table at :831-832 and the prose at :866. These are the rows #11034 split. Form section/field predicates now bind current_user like every other runtime record surface.
2. content/docs/ui/views.mdx:433 carries the same claim independently, verbatim:
"runtime forms bind record (+ previous, parent) — not current_user, which is unbound at field level and would fault the predicate open"
⚠️ This one is not a cross-reference to (1); it is a second copy that has to be corrected on its own.
3. content/docs/protocol/objectui/layout-dsl.mdx:862-863 — a bare-string authoring trap, adjacent but distinct. This is not about the binding; it is about the dialect, and it is worth fixing while the page is open because the example on it is the exact shape that breaks:
- the objectui form renderer treats a bare string predicate as CEL (
fieldRules.tstoExpression defaults dialect to 'cel'); SchemaRenderer.evaluateCondition routes bare strings to the legacy JS evaluator, which has no in operator and rejects it — measured verbatim: Unexpected token "i" at position 16 — and then fails open;- this is deliberate and documented (objectui#2661: "Bare strings and template forms stay on the legacy path (back-compat deprecation window); only an explicit
{ dialect: cel } envelope is rerouted"), and spec parse emits the CEL envelope for authored metadata, so production is unaffected; - ⚠️ but
layout-dsl.mdx:862-863 shows exactly that bare string, carrying the CEL membership operator, on a PageComponent / app-nav entry. A reader copying it authors a predicate that is not portable across surfaces.
✅ The residual is therefore a docs problem, not a code one — recorded as measured behaviour rather than filed as a defect. It caught the objectui dev's first pin run, which is how it surfaced.
Suggested scope
Correct (1) and (2) to state the current binding, and re-author the example in (3) into the canonical { dialect: 'cel' } envelope (or drop the membership operator from the bare-string example). ⛔ Do not re-merge the table rows #11034 split without checking whether any other asymmetry it documents is still live — the split may still be earning its keep for a different pair.
Pointers
Filed unassigned, no
domain:*— triage owns grading and routing.Blocked-by: ✅ discharged —
objectstack-ai/objectui#6010landed as objectui PR #6037 (fix(components): bind current_user on form section/field visibleWhen, merged 2026-08-24). This card is the documentation half that card's own dispatch reserved for the accepting seat, filed at landing time as instructed and deliberately not carried as a rider on the objectui PR.Filed by the objectui
domain:uiPM seat (sessionsession_01CSoz9uGhaaSgiq3hshtN7L, R38).What changed upstream
Until objectui#6010, form section/field
visibleWhenpredicates bound onlyrecordandprevious—current_userwas unbound, so a predicate naming it faulted open and showed the field to everyone. Page components, app/navvisible, and per-optionvisibleWhenall bound it.#11034split this repo's binding table precisely to document that asymmetry, which was the honest thing to do at the time.objectui#6010 removed the asymmetry. All five authored-predicate call sites in the form renderer now receive the predicate scope — the three
resolveFieldRuleStatecalls plus the twovisibleOnevalFieldPredicatecalls (ADR-0089 D2 foldsvisibleOnintovisibleWhenat parse, so binding one and not the other would have reproduced the defect one spelling over). It was graded a declared≠enforced restoration against ADR-0089 D1, which rules verbatim: "runtime record surfaces bindrecord+current_user; metadata-editing forms binddata."Three corrections, in two files
The objectui dev who implemented #6010 searched this repo and found the claim in two places, not one.⚠️ A card naming only
layout-dsl.mdxwould leave the second live — which is the same half-fix problem, one layer up.1.
content/docs/protocol/objectui/layout-dsl.mdx— the binding table at:831-832and the prose at:866. These are the rows #11034 split. Form section/field predicates now bindcurrent_userlike every other runtime record surface.2.
content/docs/ui/views.mdx:433carries the same claim independently, verbatim:3.
content/docs/protocol/objectui/layout-dsl.mdx:862-863— a bare-string authoring trap, adjacent but distinct. This is not about the binding; it is about the dialect, and it is worth fixing while the page is open because the example on it is the exact shape that breaks:fieldRules.tstoExpressiondefaultsdialectto'cel');SchemaRenderer.evaluateConditionroutes bare strings to the legacy JS evaluator, which has noinoperator and rejects it — measured verbatim:Unexpected token "i" at position 16— and then fails open;{ dialect: cel }envelope is rerouted"), and spec parse emits the CEL envelope for authored metadata, so production is unaffected;layout-dsl.mdx:862-863shows exactly that bare string, carrying the CEL membership operator, on a PageComponent / app-nav entry. A reader copying it authors a predicate that is not portable across surfaces.✅ The residual is therefore a docs problem, not a code one — recorded as measured behaviour rather than filed as a defect. It caught the objectui dev's first pin run, which is how it surfaced.
Suggested scope
Correct (1) and (2) to state the current binding, and re-author the example in (3) into the canonical
{ dialect: 'cel' }envelope (or drop the membership operator from the bare-string example). ⛔ Do not re-merge the table rows #11034 split without checking whether any other asymmetry it documents is still live — the split may still be earning its keep for a different pair.Pointers
layout-dsl.mdx:824teachesuser.hasRole('admin')inside a CELvisibleWhen, buthasRoleexists nowhere in spec or core — the example faults and fail-softs to visible #11034 — the PR that split the binding table to document the asymmetry.visibleWhenbinds nocurrent_user, so position-gated visibility is expressible on pages but not on forms — the asymmetry was undocumented and the docs asserted the opposite (lands in objectui) #11411 — the original cross-repo measurement; note it labels the "record purity" rationale a hypothesis ("There is a defensible design story"), not a ruling — the objectui dev searched for a recorded ruling to the contrary and found none, only ADR-0089 D1 pointing the other way.visibleOn→visibleWhenparse fold.