Uh oh!
There was an error while loading. Please reload this page.
docs(spec,lint): a form FIELD visibleWhen binds current_user — re-measure the three stale text sites - #12930
Conversation
…-measure the three stale text sites objectui#6010 bound the host predicate scope on the form renderer's authored- predicate call sites, so a runtime form FIELD `visibleWhen` / `visibleOn` now resolves `current_user` and the ADR-0068 D1 aliases. Three texts shipped by this repo still asserted the opposite, and that per-option `visibleWhen` was "the only `*When` surface where it resolves". - `packages/spec/src/ui/view.zod.ts`: `FormFieldSchema.visibleWhen`'s doc block and its `describe()` state the binding plus the two limits it does not remove — it is a rendering rule nothing on the write path evaluates, and the scope is the host's, so it is empty (and fails open) on the public standalone form route. - `content/docs/references/ui/view.mdx`: regenerated from the above, never hand-edited (`gen:docs`; two `FormField` rows). - `packages/lint`: the field-rule prescription is re-grounded on ENFORCEMENT — the rule validator evaluates a per-option predicate on every write — instead of on exclusivity, and names the form-view field predicate only to refuse it as a destination for a server-enforced object rule. The gate script's layer table splits the folded cell and is re-measured at objectui `f241a4d`. The `FormSectionSchema.visibleWhen` slot is deliberately NOT swept: its verdict was re-measured and has changed too (objectui#6110 / objectui#6111 both landed), which is a different card — the evidence and three further stale sites are recorded in the follow-up issue rather than fixed here. No schema, validation or verdict change: `check:authorable-surface` is green and `FIELD_RULE_BOUND_ROOTS` is untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
📓 Docs Drift CheckThis PR changes 2 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e473b945ed0389383bdff5c9b10304a3521695c9 && git checkout e473b945ed0389383bdff5c9b10304a3521695c9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 750fff55921e1e4a6906cbe30c22ec87cf94350b a2c6806865edd91cc5c40e5cf9acbf899888041c && git checkout -B drift-repro 750fff55921e1e4a6906cbe30c22ec87cf94350b && git merge --no-ff a2c6806865edd91cc5c40e5cf9acbf899888041c
node scripts/docs-audit/affected-docs.mjs --json 750fff55921e1e4a6906cbe30c22ec87cf94350b
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#11813
objectui#6010 bound the host predicate scope on the form renderer's authored-predicate call sites, so a runtime form FIELD
visibleWhen/visibleOnnow resolvescurrent_userand the ADR-0068 D1 aliasesuser/ctx.user/os.user. Three texts shipped by this repo still asserted the opposite, and that per-optionvisibleWhenwas "the only*Whensurface where it resolves".Documentation carried inside code. No schema, validation or verdict change:
check:authorable-surfaceis green (the legal metadata set is byte-identical) andFIELD_RULE_BOUND_ROOTSis untouched.What changed
Site 1 —
packages/spec/src/ui/view.zod.ts,FormFieldSchema.visibleWhen. The doc block and thedescribe()now state the binding, together with the two limits it does not remove — both of which fail in a direction an author does not notice:visibleWhen.packages/objectql/src/validation/rule-validator.tsevaluates fieldreadonlyWhen/requiredWhenand per-optionvisibleWhen, and that is the whole list — so a role test written here hides a control and protects no data./f/:slug) is mounted outside any provider deliberately — an anonymous visitor has no principal — so the root is unbound there, the predicate faults, and visibility's fallback istrue. The authed standalone route (/forms/:name) publishes the session principal and binds normally.Site 2 —
content/docs/references/ui/view.mdx. Regenerated, never hand-edited (pnpm --filter @objectstack/spec gen:docs). The diff is exactly two lines: theFormField.visibleWhenrow at :163 and the same row nested underFormSection.fields[number]at :325. The threeFormSection.visibleWhenrows are untouched — see the fence below.Site 3 —
packages/lint. ThefieldRuleRootIssueprescription no longer grounds "move it to the option's ownvisibleWhen" on exclusivity; it grounds it on enforcement — the rule validator evaluates a per-option predicate on every write — and names the form-view field predicate only to refuse it as a destination for a server-enforced object rule, since moving one there would trade a loud lint error for a silent enforcement gap. The gate script's layer table splits the folded cell (object field / form sectionwas carrying the view form field layer's verdict as well) and is re-measured at objectuif241a4d.The section slot was re-measured, and its verdict HAS changed — filed, not swept
The card and the dispatch both fenced
FormSectionSchema.visibleWhenout of this PR as a different verdict, conditional on a re-measurement. The re-measurement was done and the fenced premise is falsified: both halves it rested on have since landed. The section text is therefore left byte-identical here, and the evidence is filed as #12914 rather than acted on — reporting it is what the fence asks for; sweeping it is what the fence forbids.apps/console/src/components/FormPage.tsxnow readsusePredicateScope()(:1568) and threads it into all three evaluators.isSectionVisibletakes apredicateScopeparameter (:648-660) and is called with it at :1849. The card measured it passingundefined.ObjectForm.tsx(:1222),SplitForm.tsx(:386),ModalForm.tsx(:721) andDrawerForm.tsx(:597) copy the authoredsection.visibleWhenonto thesection-dividerpseudo-field, andpackages/components/src/renderers/form/form.tsxevaluates that predicate withpredicateScopebound (:1296-1311, :2179-2204). There is a dedicated pin,sectionVisibleWhen-6111.test.tsx.usePredicateScope()resolves tobuildExpressionScope()(packages/app-shell/src/providers/ExpressionProvider.tsx:82-89), which returnscurrent_userplus the ADR-0068 aliases andapp/data/features.Measured in the objectui checkout at
origin/main@f241a4d; every path above is byte-identical at the local checkoutefdc6c6(git diff --stat HEAD origin/mainover those paths shows one unrelated test fixture and nothing else).#12914 also records three further stale sites this card's fences exclude:
data/field.zod.ts'sSelectOptionSchema.visibleWhen,shared/editability-boundary.ts's option prescription, and thevisibleWhenconsequence cell invalidate-expressions.tswhose renderer half moved with objectui#6010. None of them is touched here. #12914 remains open.Pins
git grepover the retired sentences found one pin:packages/lint/src/validate-expressions.test.ts, whose comment at the prescription assertion quoted "the one*Whensurface that bindscurrent_user". It moves in this PR, and its three existing assertions (option's own visibleWhen,readable: false,falls back to VISIBLE) are unchanged and still pass. Two assertions are added: the message names therule validatorgrounding, and the retired exclusivity claim cannot come back.Verification
Union re-run at the final commit
a2c680686(working tree identical to HEAD), all exit codes captured before any pipe:pnpm --filter @objectstack/spec check:generated— "All 14 generated artifacts are up to date", includingcheck:docsandcheck:authorable-surface.pnpm --filter @objectstack/spec run check:liveness— green, and it asserts "everypath:NNNcitation names a line that file actually has", which is the anchor-drift risk a doc-block edit inview.zod.tscarries.check:strictness-ledger,check:empty-state,check:variant-docs,check:type-check-coverage,check:query-options-erasure,check:where-matcher,check:engine-double-contract,check:nul-bytes,check:doc-authoring,check:merge-driver— all exit 0.pnpm --filter @objectstack/lint run check:doc-formula-expressions— "self-test: 57 cases passed", then the corpus run green.pnpm --filter @objectstack/lint run check:doc-security-posture— green.pnpm --filter @objectstack/lint test— 81 files, 2295 passed, 5 skipped.pnpm --filter @objectstack/spec test— 440 files, 11646 passed.pnpm --filter @objectstack/lint typecheckandpnpm --filter @objectstack/spec typecheck— clean. Note the lint package'stsconfig.jsonexcludes**/*.test.ts, verified withtsc --noEmit --listFiles(0 hits for the edited test file), so that green says nothing about it; its coverage comes from the vitest run above.pnpm lint(repo-wideeslint . --no-inline-config) — exit 0. Run in full rather than narrowed.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, not from the dispatch list, and everything it named was run except as noted below.Not measured, with reasons:
check:type-check-debt --re-measureneeds the whole workspace built and is CI's run;scripts/pm/check-half-states.mjsexits 3 (PREREQUISITE NOT MET— this container has no GitHub credential), which its own text calls "no reading at all", and it is unrelated to this diff;check:react-declaration-paritycannot run in this repo at all (it needs objectui'ssdui.manifest.json).Landing
Draft on purpose. The diff touches
packages/spec/src/**, so the review chain owns enqueue — do not flip ready and do not arm auto-merge from here.Generated by Claude Code