Repository navigation
fix(components): a boolean with a CEL default is left to the server on create (objectui#12121) - #12133
Merged
objectstack-fleet[bot] merged 2 commits intoOct 11, 2026
Conversation
…server (objectui#12121) The form renderer starts an unsupplied two-state control at `false` (cloud#972). On a create form that included a boolean whose declared `defaultValue` is a runtime instruction (a CEL envelope or a runtime token), so the create payload carried `false` and `ObjectQL.applyFieldDefaults`, which fills only a key that arrives absent or null, never evaluated the declaration. The seed loop now skips a field `isServerOwnedValue` calls server-owned, the verdict the "set on save" hint and the `required` suppression already read. `previousRecord` and `isCreateForm` move above the seed so it can read the create signal. An untouched such boolean is empty, shows the hint, and is dropped from the create payload by `omitServerResolvedDefaults`. A plain boolean still seeds `false`, and an edit form still seeds it too. Claude-Session: https://claude.ai/code/session_01TYgwmFK1q4KJ6Qq2WRLzsD Co-authored-by: Claude <noreply@anthropic.com>
…y layout (objectui#12121) The objectui#12108 hint suite said a boolean never shows the hint because the renderer seeds an unsupplied two-state control `false`. objectui#12121 makes that seed skip a server-owned field, so the docblock now states the new rule, and a boolean with a CEL default joins OBJECT_SCHEMA and SERVER_FILLED: the hint is drawn under it in every layout, and the create payload omits it. Claude-Session: https://claude.ai/code/session_01TYgwmFK1q4KJ6Qq2WRLzsD Co-authored-by: Claude <noreply@anthropic.com>
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
|
1 similar comment
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-12121-runtime-default-boolean-unseeded
branch
October 11, 2026 10:10
This was referenced Oct 11, 2026
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 #12121
Clause-②: no
What changed
The create form's boolean seed (cloud#972) no longer writes
falseover a default the server fills.packages/components/src/renderers/form/form.tsx, thedefaultValuesmemo: the seed loop skips a field whenisServerOwnedValue(f, isCreateForm)from@object-ui/coreis true. That is the verdict the "set on save" hint (objectui#12108) and the create-moderequiredsuppression already read, so the hint, the suppression and the seed now agree.previousRecordmemo andisCreateFormmove, unchanged, above the seed memo, because the seed now reads the create signal. Their comment no longer counts the call sites.undefined,omitServerResolvedDefaultsdrops the key, andObjectQL.applyFieldDefaultsevaluates the declaration. A value the user sets,falseincluded, is submitted as usual.false, and an edit form still seeds an unsupplied booleanfalse.packages/plugin-form/README.md: the "set on save" section said the hint is never drawn on a boolean, because the renderer seedsfalse. That stopped being true here, so the bullet is replaced with the new rule.Why
isServerOwnedValueand not a bareisRuntimeDefaultcallTriage named
isRuntimeDefault. Measured on the field object the memo walks: the declared default is not atf.defaultValue. It sits atf.field.defaultValue, the resolved object-field metadata the object-bound builders stash.isServerOwnedValueis the existing single derivation of "read that slot, create forms only, classify withisRuntimeDefault".form.tsxalready imports it and calls it for the hint and the rule state. CallingisRuntimeDefaultdirectly would restate the slot and the create gate, which is the second derivationserver-owned-value.tsexists to prevent. No classifier is added.Measurements (hypotheses from the dispatch)
BOOLEAN_WIDGET_TYPESreader in the file, the visibleWhen clear-on-hide, only treatsfalseon a two-state control as "held nothing", and it seeds nothing. The dirty check and the defaults-reset window that the seed's comment names compare against the memo's output. The built-in checkbox and switch branches render the value as given. Nofalsecoercion exists in the submit path.packages/core/dist.index.d.tsre-exports./validation/index.js, which re-exports./server-owned-value.js, which declares bothisRuntimeDefaultandisServerOwnedValue.omitServerResolvedDefaults: it lives inpackages/plugin-form/src/schemaDefaults.ts, called fromwritePayload.ts,ModalForm.tsx,DrawerForm.tsxand the console'sFormPage.tsx. It iterates the payload's own keys and drops one whose declared default is a runtime default and whose value is empty byisMissingForRequired. An absent key is not visited, and anundefinedone is dropped.f.field.defaultValue, notf.defaultValue(see above).required: confirmed with no extra fix.resolveFieldRuleStatereturnsrequired: falsewheneverserverOwnedValueis true, static flag included. The new pin submits arequiredCEL-default boolean untouched: no required marker, no "is required" message, andonSubmitreceivesactive: undefined.checkbox/switchbranches render Radix withchecked={value}. Withundefined, the control renders unchecked (aria-checked="false", not indeterminate). The first click logs Radix's dev-onlyconsole.warn"Switch is changing from uncontrolled to controlled" (Checkbox likewise). The submitted values are correct. The object-bound path rendersfield:booleanthroughBooleanField, which passeschecked={!!value}and stays controlled. I left the built-in branches alone: they are outside this card's surface (the seed only), and the warning is dev-only. See Acceptance notes.End to end through the real containers (a one-off measurement, not committed)
A throwaway test rendered
ObjectFormwithregisterAllFields()in all seven layouts. The object hadactive: boolean, required, defaultValue CEL true,plain: boolean,literal: boolean, defaultValue true. Results:{"literal":true,"plain":false,"title":"T"}andactiveis not an own property. The hint is drawn underactivein all seven layouts, the wizard included, with no required marker."active":falseand no hint is drawn. That is the card's defect, reproduced.Tests
New pin:
packages/components/src/renderers/form/__tests__/form-boolean-seed-runtime-default-12121.test.tsx. Five cases each for the built-inswitchandcheckbox:undefined, and a plain boolean submitsfalse(cloud#972 control).requiredCEL-default boolean is not refused and has no required marker.true, then a user-setfalse, are each submitted.previousValuespresent) still seedsfalse.Ablation, run with the fix committed at
06f640dvia objectstack'sscripts/ablation-replace.mjs:00d96b1236cbto9ca086f2655f.00d96b1236cb),git diff HEADis empty, and the anchor count is back to 1.@object-ui/coreand@object-ui/componentstosrc.Runs (all at
06f640d, through the shared verify lock):pnpm --filter '@object-ui/components^...' build: exit 0, 8 projects.pnpm --filter @object-ui/components type-check: exit 0. Itstsconfig.test.jsonincludessrc/**/*.test.tsx.pnpm exec vitest run packages/components/, in 4 shards because a single run overran the 10-minute foreground cap: 94 + 94 + 94 + 93 files. 374 passed and 1 skipped. Tests: 3833 passed, 24 skipped, 0 failed.pnpm exec vitest run packages/plugin-form/in 2 shards: 173 files passed (all 173 tracked). 2127 tests passed, 1 skipped.apps/console/src/components/FormPage.serverDefaults.test.tsx: 3 files, 26 tests passed.scripts/__tests__/: in 4 shards: 181 files (179 passed, 2 skipped, all 181 tracked), 5452 tests passed, 2 skipped.check-changeset-presence,check:changeset-claims,check:pending-changeset-literals,check:new-line-citations(0 new),check:control-bytes,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shapeandcheck:phantom-deps: all exit 0.form.tsxhas 70 warnings both before and after, the same rule and message multiset. The new test has 4no-explicit-anywarnings, the same shape as its sibling tests.apps/consolebuild pluscheck:eager-closuredoes not fit the shared box's foreground cap while the lock queue runs at 5 to 9 minutes. The source delta is one guard line and one added memo dependency, and the moved block is unchanged.Acceptance notes
packages/plugin-form/src/__tests__/serverDefaultHint-12108.test.tsxsays the hint is "Not a boolean: the renderer seeds an unsupplied two-state controlfalse(cloud#972), so it is never empty". This change makes that false. The claim's file surface does not cover that file, so I left it. The suggested edit is to drop that sentence, or to add a boolean CEL field to itsOBJECT_SCHEMAandSERVER_FILLED. The throwaway measurement above shows that would pass in all seven layouts.switch/checkboxbranches when an unseeded control is first toggled. These branches are reached for an object field only through a form-viewwidget: 'switch'/'checkbox'override. Behaviour and payload are correct, and production builds resolve Radix'sIS_DEVELOPMENTto false. Owner if wanted: whoever next edits those twocasebranches inform.tsx.true). The hint is the explanation triage ruled for. To submit an explicitfalse, the user turns the control on, then off.packages/core/src/validation/server-owned-value.tsdoes not name the seed. It is not false: the seed readsisServerOwnedValue, which that list already covers.Files
packages/components/src/renderers/form/form.tsxpackages/components/src/renderers/form/__tests__/form-boolean-seed-runtime-default-12121.test.tsx(new)packages/plugin-form/README.md: a doc that describes the changed behaviour, pre-authorised by the dispatch.changeset/12121-runtime-default-boolean-unseeded.md(@object-ui/componentspatch)Dispatched by the
domain:uiseat 2 PM, sessionhttps://claude.ai/code/session_01TYgwmFK1q4KJ6Qq2WRLzsD.Generated by Claude Code