Skip to content

Port the union-arm type-mismatch check into the hoisted sdui-parser — the half of the lockstep debt that CHANGES what this copy accepts and rejects #12814

Description

@huangyiirene

Split out of #12810 by the triage seat (session session_01Aujz2zykf5LXt3T98gRsGe), on that card's own recommendation — "They may deserve splitting." ⛔ All measurement below is #12810's, not re-derived here; read it there for the evidence and the controls.

Why split.#12810's two items need different treatment, and folding them drags the cheap one behind the expensive one:

itemshapetreatment
1dashboard-widget-options (absent here entirely)additive: a new warning code reporting an already-inert statesame shape as #12719 — stays on #12810, off the manual floor
2 — union-arm type-mismatch (this card)⚠️changes what this copy accepts and rejectsClause-② content leg; contract-review tier

What is missing here

objectui's checkType is built on inputTypeArms(input.type) (src/input-type.ts, absent in this repo) and clears a prop when any declared arm accepts the value. This repo's checkType is the older single-arm switch (input.type). Two measured consequences:

  • A manifest input declaring a union type falls through this repo's default: return null and draws no diagnostic at all, while objectui checks every arm.
  • Where no arm accepts, objectui emits onetype-mismatch naming every arm, at error severity when an enum arm is present. This repo can only emit the single-arm form ⇒ the same value yields a different code/severity pair across the copies.

Why this is Clause-② and not a mechanical port

⛔ This is not#12719's "reports an already-inert state" shape. Today a union-typed input draws nothing; after the port it can draw an error. That is a change to what the save gate accepts and rejects, which is the content legneeds:contract-review is attached at filing and the dispatch must declare Clause-②: yes.

⚠️But it is not a new contract decision either, and that is why this is pm:queue rather than the decision inbox. The underlying ruling is objectui#3832, already made on the other copy. #12719 establishes the invariant both copies owe each other — "both copies byte-agree on the accepted grammar and on diagnostic codes" — so not porting is the drift, and porting applies an existing ruling to the lagging copy. ⇒ Contract-review tier, ⛔ not a maintainer question. If the implementer finds the port would require deviating from objectui#3832's behaviour rather than matching it, stop and report — that would be a new decision.

⚠️ Sequencing — settle this before or with the manifest wiring, ⛔ not after

The blast radius is currently bounded by a separate unfixed gap: this repo resolves no sdui.manifest.json (none in the tree; @objectstack/console/dist/sdui.manifest.json absent), so resolveSduiManifest() returns undefined and validateJsxPages runs parse-onlyvalidateTree is not reached from the production gate at all today. ⇒ The drift is latent. Wiring the manifest is what turns it author-visible, so this card should land before or with that wiring. That wiring is the second gap recorded on #12719 and is still unowned.

⚠️ Interaction with an open maintainer decision

objectui#6614 (needs-user-decision) asks whether interpretBrace should materialise a JS literal subset. If it rules to widen the grammar, the set of values reaching checkType changes — which may reshape what this port should assert. ⛔ Check #6614's state at dispatch: if it is still open, say so in the report and consider whether the port is stable under either outcome. It probably is (arm checking is orthogonal to what parses), but that is a reading to take, not to assume.

Not drifted, measured — ⛔ do not re-derive

interpretBrace itself is byte-identical across the copies (sha256 of the extracted function body agrees, and the comparator was proved able to detect a disagreement by mutating one side first). The accepted grammar is genuinely in lockstep; the gap is entirely on the diagnostic-code side.

Refs: #12810 (parent, item 1 and the full measurement) · #12719 (the inert-expression port and the invariant) · #11148 (the same two-copy port pattern) · objectui#3832 (the ruling being ported) · objectui#6614 · ADR-0078 · ADR-0080.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions