Skip to content

fix(app-shell): seed the flow-node boolean control from the declared defaultValue (objectui#6830 arm A) - #8473

Merged
os-justin merged 1 commit into
mainfrom
claude/issue-8451-flownode-boolean-declared-default
Sep 8, 2026
Merged

fix(app-shell): seed the flow-node boolean control from the declared defaultValue (objectui#6830 arm A)#8473
os-justin merged 1 commit into
mainfrom
claude/issue-8451-flownode-boolean-declared-default

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #8451 — objectui#6830 arm A ("show, do not write", triage 2026-09-04), the
boolean half. The select half is not addressed here and stays open on objectui#8450.

Base 1706d8be4 · installed @objectstack/spec 17.3.0.

What changed

FlowNodeConfigField's case 'boolean' drew value === true. That expression flattened
an absent key and a stored false onto the same unchecked box although the runtime
treats them oppositely on a key the spec defaults to true — on an approval node omitting
escalation.notifySubmitter, the inspector said "Notify submitter: off" for a flow that
notifies. The control now shows the value in effect:

const checked = isUnsetFieldValue(value) ? field.defaultValue === 'true' : value === true;
  • unset → the declared default, in the table's own 'true'/'false' spelling — the one
    controllerAdmits already compares an unset showWhen controller against;
  • stored=== true, unchanged. Deliberately not widened to also accept a stored
    string 'true': that would be a lenient renderer-side alias for off-spec metadata
    (AGENTS.md #0.1), and the producer is ours to fix.

isUnsetFieldValue is exported from flow-node-config.ts so the three sites that must answer
"has the author stored anything here" — the re-show rule, the showWhen resolver, and now
the control — share one definition instead of three copies of === undefined || === null || === ''. Without that, one node could render a gate that says "unset, so use the default"
beside a control that says "stored, so ignore it".

Nothing is written. Rendering a seeded control patches the draft exactly zero times
(pinned); a node that never carried the key still ships without it.

The affordance's shape, and why it carries no caption

An absent key reads as distinct from a stored false through the checkbox state itself:
declared-true + absent → checked; stored falseunchecked. Those were
outerHTML-identical before and are not now.

The card budgeted "one i18n key pair" for a caption naming the default. No caption ships,
and that is the answer to the wrong declared default
— see below. Absent-vs-stored-true
deliberately still render alike: both mean true at runtime, so drawing them differently
would be inventing a distinction the metadata does not have. The distinction that does
exist — and that this card is about — is absent vs stored-false.

The one wrong declared default: I ran objectui#6620's own restart probe, and it fires

Exactly two boolean fields in the offline table declare a default. One of them is the
wrong one, so a caption asserting "this is the declared default" would have shipped a false
statement on half the surface it annotates:

field declares spec 17.3.0 applies to an omitted key
approval.escalation.notifySubmitter 'true' true
approval.escalation.enabled 'false' true ❌ objectui#6620

Neither of the two options the card offered survived measurement:

  • Deriving that row from the spec cannot be display-only without making the panel
    contradict itself (a ticked "SLA escalation" above four hidden dependants). Feeding both
    means flipping the table's defaultValue to 'true', which changes visibility for
    every approval node omitting the key, reds a pin row that leg B did not predict
    (the offline table hides the same siblings, because it declares the gate false), and
    flips objectui#6620's tripwire in flow-node-config.inactiveRetained.test.ts. That is
    objectui#6620's fix, done from an unrelated PR.

  • Gating on objectui#6620 reads as "wait", and the measurement says it is not a wait.
    Its triage comment (5442325479) sets a mechanical restart criterion:

    Restart-when: the installed @objectstack/spec in this repo parses an escalation block
    with enabled omitted as enabled === true … While it prints false, the hold is
    correct and there is no defect to fix.

    It prints true. On installed 17.3.0,
    ApprovalEscalationSchema.safeParse({ timeoutHours: 24 }).data is
    {"enabled":true,"timeoutHours":24,"action":"notify","notifySubmitter":true}. The
    restart condition is met; objectui#6620 is live, not latent, and still carries
    pm:on-hold. Reported for triage, not acted on here.

So this PR does the third thing: it ships the seed and no words. The seed renders
escalation.enabled byte-identically to before (unchecked — the declaration says 'false'),
so no new claim about that declaration reaches an author, and a new case pins exactly that:
the gate's control carries its label and nothing else. When objectui#6620 lands, its
one-line flip now repairs the rendered toggle as well as the gating, because the control
reads the same declaration.

⚠️ Also measured: objectui#6620's restart probe as written imports ApprovalEscalationSchema
from @objectstack/spec, where it is undefined on 17.3.0 — the probe throws
TypeError: Cannot read properties of undefined (reading 'parse'), which is easy to misread
as "not available yet, the hold is correct". The working spelling is
@objectstack/spec/automation, which is what the repo's own
flow-node-config.spec-reconciliation.test.ts already uses.

The pin: turned green, not weakened

FlowNodeInspector.declaredDefault.test.tsx13 cases → 17, all still assertions about
rendered values. Applying the implementation to the unmodified pin reproduced PR #8431's
ablation leg B exactly, by name (3 failed / 10 passed):

  • boolean: an unset key draws an UNCHECKED box, though the table declares true
  • renders identically whether the key is missing or explicitly false
  • the boolean control exists, is a checkbox, and commits the author edit

Each was rewritten against the repaired behaviour rather than deleted or softened, and every
select case is carried over untouched. Net new cases: show-do-not-write (zero patches),
a stored false beats the declared true, a field declaring no default stays unchecked
(measured on the online writer — the offline table has no undeclared boolean), and the
objectui#6620 no-worded-claim case. Two existing cases were strengthened: the online
default: true is now asserted to reach the control, and the commit row now exercises both
directions (seeded-true → writes false; stored-false → writes true).

Would an implementation strictly worse than the bug pass? No — measured

Two ablations, both mutating the read site from the committed tree, both proved to reach
disk by git hash-object against the HEAD blob plus removed-text/injected-text grep counts in
both directions, both restored by state (git diff HEAD empty and hashes equal).
HEAD blob of FlowNodeConfigField.tsx: 085103868528ff4bd971a7d6bd00776797163f4b.

leg mutation mutated blob result
A the seed removed (const checked = value === true) d45bb482d38da528ca61a87241fd27fbef7e7af8 5 failed / 12 passed
B always checked (const checked = true) 2937d11f607172fffcaf7af26e73c91f848f7d02 5 failed / 12 passed

Leg A red rows: boolean: an unset key draws a CHECKED box, because the table declares true ·
boolean: showing the default WRITES nothing — the node still omits the key ·
a gate whose default is true reveals its siblings for a node that omits the key ·
renders differently when the key is missing than when it is explicitly false ·
the boolean control exists, is a checkbox, and commits the author edit.

Leg B red rows: boolean: a stored FALSE beats the declared true and draws an UNCHECKED box ·
boolean: a field declaring NO default still draws unchecked when unset ·
boolean: the #6620-wrong declaration ships NO worded claim (objectui#6620) ·
renders differently when the key is missing than when it is explicitly false ·
the boolean control exists, is a checkbox, and commits the author edit.

Leg B is the answer to the question: a control that renders always checked satisfies
"an absent key shows checked" and is strictly worse than the bug. The stored-false rows
refuse it, and they are marked ⛔ load bearing in the file so they are not later softened
into "differs from absent" — which an always-checked control also fails only by accident.

Verification

  • pnpm exec vitest run …/FlowNodeInspector.declaredDefault.test.tsx17 passed, exit 0.
  • pnpm exec vitest run packages/app-shell/src/views/metadata-admin/238 files, 2481 passed /
    1 skipped
    , exit 0. Declared narrowing, with the measurement that it excludes nothing:
    packages/app-shell carries 650 test files and this run covered 238 of them. The whole-package
    run was attempted and the container killed it at its foreground ceiling (exit 144), so the
    narrowing is measured rather than assumed — a repo-wide grep for importers of the three changed
    modules (flow-node-config, FlowNodeConfigField, isUnsetFieldValue) returns 21 files, all
    under views/metadata-admin/
    . The single hit outside that directory,
    providers/ExpressionProvider.tsx:324, is a prose comment naming the path, not an import; the
    same grep shape with a lit control (MetadataClient) does return files outside the directory.
    CI runs the full farm.
  • pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build — exit 0 (closure
    built before type-checking).
  • pnpm --filter @object-ui/app-shell type-check — exit 0 (tsc --noEmit and
    tsc -p tsconfig.test.json). The pin file is in the test program:
    tsc -p tsconfig.test.json --listFiles lists it once, with FlowNodeConfigField.tsx beside
    it and a zero-hit negative control.
  • pnpm --filter @object-ui/app-shell lint — exit 0, 0 errors; eslint --format json on
    the three changed files reports errors=0 warnings=0 for each, against a lit control that
    does report warnings.
  • check:control-bytes ✅ OK · check:vi-mock-specifiers ✅ OK · check:vi-mock-inherit
    ✅ OK · check:designer-field-key-parity OK · check:i18n-keys OK.
  • check-governed-queue-guard --test on all four changed paths —
    ✅ NOT GOVERNED — 4 path(s) checked against 5 governed surface(s); none matched.
  • check-changeset-presence✅ 3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s). check-changeset-no-major · check-changeset-fixed
    · check-changeset-overwrite .

Changeset

@object-ui/app-shell: patch. No prop, option or metadata key is added and no authored
document changes meaning; what changes is that one control stops contradicting the runtime
for metadata that already parses. minor was weighed and not taken — nothing here is a new
capability an author can reach for. (major is forbidden in this repo.)

🤖 Generated with Claude Code

https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S


Generated by Claude Code

…defaultValue

objectui#6830 arm A ("show, do not write", triage 2026-09-04), the boolean
half — objectui#8451. The select half stays untouched: it is blocked on
objectui#8450.

The control drew `value === true`, which flattened an ABSENT key and a stored
`false` onto one unchecked box although the runtime treats them oppositely on a
key the spec defaults to true. It now shows the value in effect — the stored
boolean, else the declared `defaultValue` in the same 'true'/'false' spelling
`controllerAdmits` already resolves an unset controller against. Nothing is
written; the first author edit still commits an explicit boolean.

`isUnsetFieldValue` is exported from `flow-node-config.ts` so the three sites
that have to answer "has the author stored anything here" (the re-show rule,
the `showWhen` resolver, and now the control) share one definition instead of
three copies of `=== undefined || === null || === ''`.

⛔ No caption naming the default is rendered, deliberately. Of the two boolean
fields the offline table declares a default for, `escalation.enabled` declares
the OPPOSITE of what installed `@objectstack/spec` 17.3.0 applies to the
omitted key (objectui#6620), so a "(default)" label would have shipped that
wrong claim to authors in words. The seed alone leaves that field rendering
byte-identically to before, which is pinned.

PR #8431's pin is turned green against the repaired behaviour rather than
weakened: its three leg-B rows now assert the new states, and the stored-`false`
rows are kept load bearing so an always-checked control — an implementation
strictly worse than the bug — still fails.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3473.5 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index-DWuBqL04.js
Status PASS

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 498.87KB 114.10KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 10.12KB 3.28KB
data-objectstack (index.js) 191.36KB 53.16KB
fields (index.js) 243.15KB 61.40KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 49.00KB 13.91KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.52KB 46.34KB
plugin-dashboard (index.js) 131.48KB 34.45KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 248.78KB 63.98KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.58KB 56.63KB
plugin-kanban (index.js) 55.40KB 15.71KB
plugin-list (index.js) 112.74KB 27.70KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.33KB 3.25KB
plugin-view (index.js) 84.54KB 20.84KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-justin
os-justin marked this pull request as ready for review September 8, 2026 01:27

Copy link
Copy Markdown
Collaborator Author

PM contract review — accepted, flipped to ready, auto-merge armed. You refused both options I offered and the refusal is right.

The wrong declared default: neither of my options survived measurement

I offered "gate on objectui#6620" or "derive that row from the spec". You measured that exactly TWO boolean fields in the offline table declare a default — notifySubmitter ('true', correct) and escalation.enabled ('false', wrong on spec 17.3.0).

a caption asserting "this is the declared default" would have shipped a false statement on HALF the surface it annotates.

Your answer — ship the seed and no words — is better than either of mine, and the reason it works is that the seed renders escalation.enabled byte-identically to before (unchecked), so no new claim about that declaration ever reaches an author. Then you pinned the absence, so a caption cannot be added later without reddening.

The omitted i18n key pair is the answer, not a shortfall. My card budgeted "one i18n key pair" as part of the scope. That key pair would have paid for exactly the caption that puts the wrong declaration into words. Not spending it is the fix.

Both of my named options, refuted rather than declined

  • "Derive that row from the spec" — display-only derivation makes the panel contradict itself (a ticked SLA escalation above four hidden dependants). Feeding both display and showWhen means flipping the table's defaultValue, which changes visibility for every approval node omitting the key and reddens a pin row ablation leg B did not predict — i.e. outside this card's sanctioned blast radius. That is objectui#6620's fix performed from an unrelated PR.
  • "Gate on objectui#6620" — reads as wait, and there is nothing to wait for: that card's own restart probe fires on the installed spec today.

Beyond scope in the right direction

Exporting isUnsetFieldValue so the three sites that must answer "has the author stored anything here" share one definition — the re-show rule, controllerAdmits, and now the control — is more than the card asked for and is the correct shape. Three copies of that question is the drift generator this repo keeps paying for elsewhere.

And the load-bearing marker on the stored-false row matters: an always-checked control fails that row only by accident if it is later softened into "differs from absent". Marking it is what keeps ablation leg B meaningful.

⚠️ The finding that matters most is about a probe, not this code

objectui#6620's own restart probe cannot produce the reading it asks for: it spells require('@objectstack/spec'), where ApprovalEscalationSchema is undefined on 17.3.0, so it throws TypeError instead of printing a boolean — and it fails toward leaving the card asleep. Working specifier is @objectstack/spec/automation.

A restart probe that fails safe-toward-dormant is worse than none: the card stays on hold and the failure looks like "not yet". Same class as a pin that cannot go red. Acting on it below.

Also recorded: the comment that objectui#6620 describes as its tripwire reads only the TABLE and never the spec, so a spec bump alone can never redden it. And PR #8431's report and objectui#6620 both state FlowConfigField.defaultValue has "exactly one consumer"after this PR there are two, which is in objectui#6620's favour: its one-line flip now repairs the rendered toggle as well as the gating, the symptom in its own title.

patch is right — the seed adds no capability an author can reach for.


Generated by Claude Code

@os-justin
os-justin enabled auto-merge September 8, 2026 01:27
@os-justin
os-justin added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit c1ae1af Sep 8, 2026
34 checks passed
@os-justin
os-justin deleted the claude/issue-8451-flownode-boolean-declared-default branch September 8, 2026 01:55
os-justin pushed a commit that referenced this pull request Sep 8, 2026
Conflict in FlowNodeInspector.declaredDefault.test.tsx's docblock only, and
only in its point 1: PR #8473 (objectui#8451) rewrote the BOOLEAN half of that
paragraph while this branch rewrote its SELECT half. Resolved by taking the
incoming boolean text verbatim and re-applying the select correction on top of
it - the select now draws InspectorSelectField's own em-dash placeholder rather
than a blank trigger, which is the same fact about `defaultValue` as before.

The file's select assertions merged cleanly and are unchanged by this commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[objectui#6830 arm A, boolean half] seed the flow-node inspector's boolean control from the declared defaultValue

2 participants