Skip to content

finding(sdui-parser): the 'field' binding arm survives on the manifest READER face after #6950 retires it on the producer face — zero writers repo-wide, and objectstack carries the same three declarations #8315

Description

@os-zhuang

Observation-class finding, measured while accepting PR #8297 (objectui#6950). Filed unassigned, no labels — grading is the triage seat's.

The claim

The 2026-09-07 ruling on #6950 (director seat, decision batch #69, maintainer 「其他同意」) retires the zero-writer 'field' arm under ADR-0049, naming one coordinate: RegistryConfigLike.binding in packages/sdui-parser/src/index.ts. PR #8297 narrows exactly that one, which is correct scope discipline and was accepted as such.

The same arm survives on the manifest reader face, in two more declarations that the ruling did not name, so after #8297 lands the published package narrows on one face and stays wide on the other.

Measured on origin/main = 8f9d87a

packages/sdui-parser/src/index.ts:90    binding?: 'object' | 'field';        ← RegistryConfigLike — narrowed by PR #8297
packages/sdui-parser/src/types.ts:100   binding?: 'object' | 'field';        ← ManifestInput — RESIDUE
packages/sdui-parser/src/types.ts:138   bindings: Array<{ tag: string; input: string; kind: 'object' | 'field'; value: unknown }>;   ← ManifestValidationResult — RESIDUE

Zero writers, with a live control so the zero means something. binding: 'field' across packages/ / apps/ / examples/: 0 occurrences. The control word binding: 'object' on the same grep: 7 occurrences across 5 filespackages/core/src/data-scope/element-data-source.ts (3), and one each in sdui-parser's __tests__/compile.test.ts, __tests__/render.test.tsx, __tests__/tier.test.ts, verify.ts. So the discriminator works and the zero is a real zero, not a broken pattern.

⭐ The shadow: objectstack carries the same three declarations

Measured on objectstack-ai/objectstack origin/main = f2f6684:

packages/sdui-parser/src/index.ts:81    binding?: 'object' | 'field';
packages/sdui-parser/src/types.ts:84    binding?: 'object' | 'field';
packages/sdui-parser/src/types.ts:107   bindings: Array<{ tag: string; input: string; kind: 'object' | 'field'; value: unknown }>;

I have NOT measured which repo is upstream of which, and this card does not assert a direction. What is measured is that both repos carry a packages/sdui-parser with the same three declarations, and that this repo runs a check:upstream-port-parity gate — so the two copies are kept in step by some mechanism, and whoever owns that mechanism decides whether a retirement on one side must propagate. The objectstack half is filed as objectstack-ai/objectstack#16583; ⛔ neither card should be worked without the other being read.

⚠️ Also unmeasured, and named on the objectstack card: the 'field' writer count in that repo. The zero above is objectui's. Whoever takes either side runs the grep on their own side first.

Why this is worth a card rather than a note

The reviewing tier explicitly escalated it from "noted" to must be filed. The reason is the shape, not the size: a published type that narrows on the producer face and stays wide on the reader face is a declared-but-unenforced arm with a new asymmetry added to it — which is the exact defect class #6950 was opened about, one face over. validateTree forwards whatever a manifest says, so nothing downstream refuses a 'field' that no producer can now legally emit.

⚠️ There is a real argument for the current state being correct rather than incoherent, and it should be answered rather than assumed away: producer → reader is a subset relation, so a reader accepting a value no producer emits is merely permissive, not wrong; and the wire vocabulary is shared with a separately published @objectstack/sdui-parser. Whoever takes this decides between "narrow both faces" and "record the reader face as deliberately wider, and say why" — ⛔ what it should not stay is undecided and unstated.

Refs

Filed by the domain:spec @ objectui PM seat, session session_01QtGhnU3WnnWyiWeYQhw2aX.


Generated with Claude Code

https://claude.ai/code/session_01QtGhnU3WnnWyiWeYQhw2aX

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

    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpriority:p3

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions