Repository navigation
refactor(react,plugin-form,console): read visibleWhen only — spec 18 retires the form view's visibleOn and the page component's visibility - #12692
Conversation
…retires visibleOn and visibility @objectstack/spec 18 retires the form view field's and section's `visibleOn` and the page component's `visibility` as retiredKey tombstones naming `visibleWhen` (objectstack#23543 F4). The readers of the spec keys stop folding them back: - SchemaRenderer drops the `visibility` leg, its working-copy type member and its prop strip; BaseSchema's own deprecated `visibleOn` is a different key and stays. - plugin-form's normalizeSectionField carries a spec field's `visibleWhen` only into the runtime field's view-level slot; the runtime FormField's own `visibleOn` slot is unchanged. - The console FormPage builds field and section rows from `visibleWhen` only. The spec-parity coupling walks to the FormFieldSchema shape through a pipe when there is one, so it holds on next.2 and on spec 18; the expressions test's probe node declares `visibility` itself instead of picking it off PageComponent. Pins: a raw schema with the retired key alone gates nothing, and the same predicate under `visibleWhen` does. Claude-Session: https://claude.ai/code/session_01SdA7b5ZrdDDBDKG48XRqy7 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdA7b5ZrdDDBDKG48XRqy7 Co-authored-by: Claude <noreply@anthropic.com>
✅ 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
|
REWORK round 1 → PR #12692 ·
|
…ns at the retired visibility leg page-variables: the retired `visibility` key (bare and envelope) gates nothing, and the same predicate under `visibleWhen` (bare and envelope) does. The envelope form keeps its gating coverage on `visibleWhen`. check-doc-expression-carriage: the renderer's VISIBILITY_* arrays now hold five keys and the gate derives seven condition keys. Claude-Session: https://claude.ai/code/session_01SdA7b5ZrdDDBDKG48XRqy7 Co-authored-by: Claude <noreply@anthropic.com>
✅ 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
|
Contract reviewServed-tier: Read: card #12654's body and all four comments (triage ① Derived judgmentsThe installed spec is
② Semver levelThree changesets, ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
席位核对 · ACCEPT ·
|
Fixes #12654
Clause-②: no (narrowing)
What changes
@objectstack/spec18 retires the form view field's and section'svisibleOnand the page component'svisibilityasretiredKeytombstones namingvisibleWhen(objectstack-ai/objectstack#23543 F4, landed as objectstack-ai/objectstack#23836). The objectui readers of those spec keys stop folding them back:@object-ui/react:SchemaRendererdrops thevisibilityleg of its visibility chain, thevisibilitymember of its working-copy type, and its prop strip.BaseSchema's own deprecatedvisibleOnis a different key (the spec's page component never declared it) and is still read.@object-ui/plugin-form:normalizeSectionFieldcarries a spec form field'svisibleWhenonly into the runtime field's view-level slot. The runtimeFormField's ownvisibleOnslot (the gateform.tsxevaluates) is a different key and is unchanged.FormPagebuilds field and section rows fromvisibleWhenonly (/forms/:nameand the public/f/:slug).The narrowing (Clause-② reason)
A raw schema handed to these readers without passing through the spec's parse, carrying only the retired key, is no longer honoured: the field, section or node draws. Served metadata is unaffected, because it already reaches objectui with
visibleWhen: the spec's parse folds the old key through the 18 pre-releases, and spec 18's stored-row rehydration rewrites a stored row. Each narrowing is pinned beside its control (the same predicate undervisibleWhendoes hide):FormPage.visibleWhen.test.tsxandFormPage.conditionalRules.test.tsx(field and section);sectionFields.test.ts("does not read the retired spec-fieldvisibleOn");SchemaRenderer.expressions.test.tsx("does not read the retiredvisibilitykey").Ablations (objectstack
scripts/ablation-replace.mjs, restores proven blob == HEAD): putting back?? fd.visibleOngives 2 failed;?? override.visibleOngives 2 failed;?? sec.visibleOngives 2 failed; thevisibilityleg gives 1 failed. A firstvisibilityattempt was refused by the tool (the anchor was not consumed) and did not run.The three spec-shape couplings
sectionFields.spec-parity.test.ts: the key set is read through a pipe when there is one (.inon next.2, the plain object on 18). ThevisibleOnrow now asserts the normalizer drops it; the key stays in the spec's shape on both lines (deprecated alias, then tombstone).SchemaRenderer.expressions.test.tsx: the probe node declaresvisibilityitself instead of pickingPageComponent'svisibilitymember, which isneveron 18.flat-props-refusal-10872.test.ts: already walks pipe and lazy, and holds unchanged.PAGE_COMPONENT_NODE_KEYSkeepsvisibilitybecause spec 18 still carries it as a shape key.Green against the installed
18.0.0-next.2. The spec-18 leg is NOT MEASURED (18 is not installed); the walks hold for a plain closed object by construction.Census (H1)
form.tsx'svisibleOnreads andWizardForm's are the RUNTIME field's slot, whichsectionFields.tsfills from the spec'svisibleWhen; they are unchanged. The spec-field reader issectionFields.ts. It sits outside the claim's listed surface and is fixed in place under the bounded same-class exemption (one expression, no other claim on the file, same gate family as the spec-parity coupling already in the surface). The claim's file surface needspackages/plugin-form/src/sectionFields.ts,sectionFields.test.tsandsectionFields.blankGate-11262.test.tsadded.CommandPalette(command items),cli check(BaseSchema vocabulary) and@object-ui/types(no spec key declared live) are unchanged.Acceptance notes
SchemaForm.readVisibilitystill readsvisibleWhen ?? visibleOn, because the designer's own create and anchor schemas writevisibleOninto in-app layouts (not saved metadata). Left for its own card.normalizeSectionField's string shorthand reads an object field'svisibleOn, a key the spec FieldSchema does not declare. Dormant; noted only.BaseSchema.visibleOn(objectui's own deprecated alias) is not this card.--no-inline-configreports 2 errors on changed files; both are present on the base.Local gates (HEAD e8099b7, merged with origin/main 023087f)
Re-pinned in REWORK round 1:
page-variables.test.tsx: the retiredvisibilitygates nothing, bare and as an envelope; thevisibleWhenbare and envelope forms gate.check-doc-expression-carriage.test.ts:VISIBILITY_*holds 5 keys; the derived conditions are 7.Ablations of both go red (2 failed, 1 failed), and the restored blob 74db941 equals HEAD.
packages/components/src/__tests__: 217 files green.scripts/__tests__: 186 files green.Closure builds (react, plugin-form, console): 0. type-check (react, plugin-form, console): 0. targeted union on e8099b7: 74 files, 1520 passed. check:changeset-claims, changeset:check, check:test-path-roots, check:spec-symbols, check:new-line-citations, check:control-bytes, check:doc-json, check:doc-examples, check:doc-snippets: 0.
Provenance: built by the cloud session
session_01SdA7b5ZrdDDBDKG48XRqy7(claim6215663324) and opened by thedomain:uiseat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) from that session's final message, because a cloud session cannot open a PR from its container. The seat changed only one type spelling with angle brackets into words, and replaced the dev's own footer lines with this line.Generated by Claude Code