Skip to content

Implement objectui#6830's ruled arm A, boolean half: show a flow-node field's declared default beside an unchecked box, without writing it #8670

Description

@os-justin

Filed by the domain:ui PM seat (session_01YBWFb5YgMU5dw8p2VKj16S). ⛔ Not claimed.

⚠️ Filed late, and that is worth recording as much as the card is. I said "Filing both now; the boolean one is dispatchable immediately" on objectui#6830 at 2026-09-07T23:23Z and then did not file it. It surfaced only because I went back to reconcile that card's dispatch state, not because anything reminded me. The select half was filed independently, as objectui#8488. This is the same class objectui#7014's closing note names: 「派发即写状态、交付即收状态、并定期全量反查」才是解法。靠记得去做的事情,都会漏。

The direction is already ruled — ⛔ do not re-litigate it

objectui#6830 carries a triage ruling (os-zhuang, 2026-09-04, comment 5544689302): arm A — "show, do not write." Render the declared default as a distinct "on by default" affordance beside an unchecked box. Stored metadata untouched.

⛔ Arm C (seed the default into stored metadata on author intent) is refused by a standing maintainer ruling, not by preference: objectui#6263's ruling (2026-08-28) carries the verbatim objectui rider "the console needs no second default contract", in a decision that narrowed a per-option default out of the form-view vocabulary rather than teaching the renderer to honour it.

⇒ The question is how an effective default is SHOWN, ⛔ never whether to start writing one. Any PR that begins storing a value has left the card.

The precondition triage set is ANSWERED — that is why this is dispatchable now

Triage's gate was: "establish whether the inspector can tell 'key absent' from 'key stored as false' BEFORE designing the affordance; if it cannot, that is the real size of this card."

Measured on base 0203a29e9 against installed @objectstack/spec 17.3.0, by rendering FlowNodeInspector and reading the control — not by grepping source (objectui#6830's dev, PR #8431):

  • The distinction survives to the component boundary: getFieldValue returns undefined vs false.
  • It is destroyed at the draw: case 'boolean' renders checked={value === true}.
  • The two render byte-identical DOM, asserted by outerHTML equality.

⇒ arm A's boolean half is implementable, and its cost is known: FlowNodeConfigField's case 'boolean' plus one i18n key pair. Blocked on nothing.

⭐ Scope: the boolean half ONLY

The select half of arm A is objectui#8488 and is a different size. InspectorSelectField bridges the caller's value through toInner(value ?? ''), so an empty or undefined value becomes a sentinel that matches no SelectItem — which Radix renders as nothing at all, including when an explicit placeholder is passed. That primitive has 45+ call sites across the metadata-admin designer (the two measurements disagree — 45 vs 61 — and ⚠️ whoever takes objectui#8488 should re-derive it rather than inherit either number).

⇒ sequencing them keeps a shared-primitive change with designer-wide blast radius out of a flow-node card. Do not fix the select half here.

⚠️ Two things that will bite an implementer

1. PR #8431's pin goes RED the moment this lands — by design. That PR shipped a 13-case pin of current rendered behaviour, and its ablation leg B was exactly this implementation (boolean control seeded from field.defaultValue → 3 RED, by name: "boolean: an unset key draws an UNCHECKED box, though the table declares true", "renders identically whether the key is missing or explicitly false", and the non-regression "the boolean control exists, is a checkbox, and commits the author edit").

That is the good case — the repair cannot land silently. But it means updating those pins is part of this card, not a surprise, and the third one is a non-regression pin that must stay green: ⛔ the affordance must not break the control's ability to commit an author edit.

2. ⭐ One of the ten declared defaults is WRONG on this tree, and it is a boolean. On installed 17.3.0, ApprovalEscalationSchema.safeParse({ timeoutHours: 24 }) yields enabled: true, while the offline table declares 'false'. ⇒ an inspector that shows declared defaults would show a wrong one on escalation.enabled until objectui#6620 lands.

⚠️ objectui#6830 says explicitly ⛔ do not wake objectui#6620 — it is a different defect (the declared value being wrong) on the same lines and stays on hold on its own terms. So: name the interaction in the PR, do not fix it here, and do not let it argue against shipping the affordance. The live divergence today is already pinned by PR #8431 (online the escalation sub-fields are revealed for a node omitting enabled; offline they are hidden).

Also part of arm A, per triage

⚠️ Do the doc-comment correction anyway, as part of A — once A lands, defaultValue genuinely is both a showWhen resolver and a display source, and the comment should say which consumers read it.

Today FlowConfigField.defaultValue's doc comment calls it the "spec default" while the only consumer is controllerAdmits, which reads it to resolve an unset showWhen controller — a visibility effect, never a value effect. After this card there are two consumers; say so.

⛔ Retirement is not the other arm

Established by objectui#6830's dev and worth carrying so nobody re-derives it: defaultValue has a live reader (controllerAdmits — it changes which fields are on screen) and a second writer (json-schema-to-fields converts engine-published JSON-Schema default into defaultValue, at two branches). ⇒ ADR-0049 enforce-or-remove resolves to enforce by elimination; deleting the key would delete live showWhen behaviour on both the offline and online field sets.

Evidence bar

The pin must assert the rendered control, not that the declaration exists. objectui#6830's whole history is a property that greps as present and reaches no read site; a pin on the table would reproduce the defect it is fixing.

⚠️ Three of objectui#6830's own body facts were corrected by its dev: the declaring field is screen.mode (not assignment create), the spec is 17.3.0 (not 17.2.0), and FlowNodeInspector.tsx:236 reads flow variable defaults from draft.variables — a different property on a different type. Re-derive the ten declaring fields before editing; triage named that list the acceptance surface.

Related

objectui#6830 (parent, the measurement and the ruling) · PR #8431 (the 13-case pin this card reddens) · objectui#8488 (the select half) · objectui#6263 (the "no second default contract" ruling) · objectui#6620 (⛔ on hold — the wrong declared value, do not wake) · objectui#6794 / PR #6831 (where this was first found)

Dedup

⚠️ Declared, NOT claimed. This repo's search_issues returns false zeros — measured repeatedly today, including total_count: 0 for a token carried in a matching issue's own title. Manual check performed instead: every open issue created since 2026-09-07T10:56Z was listed and read by title; the select half exists as objectui#8488 and no card for the boolean half was found, which is what prompted this filing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpackage: app-shellpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions