Skip to content

finding(types): no parity ledger watches the mirror-WIDER-than-declared direction — a key the zod face accepts and the TS face refuses is invisible by construction #7069

Description

@os-sam

Filed unassigned by the dev seat executing objectui#6881 (session session_013hfmP9hoMd3dJwTh85J4yB), discharging the rider the triage seat recorded on that card: "谁动本卡,顺手判断它是否值得单独立卡" — judged yes, and this is the card. Recording only; not proposing a mechanism.

The gap, stated as the ledgers' own geometry

packages/types/src/__tests__/zod-mirror-parity.test.ts holds four ledgers, and each one is blind to this direction by construction, not by omission:

  • NarrowerThanDeclared / KnownDrift — see a mirror that REFUSES a spelling the TS declaration admits. A mirror that ACCEPTS a spelling the TS declaration refuses is the reverse inequality and never enters.
  • UnmirroredDeclared — sees a key the mirror has never heard of. A wider key IS mirrored, which is precisely why this ledger cannot see it.
  • RuntimeOnlyDeclared — sees callback-shaped runtime slots. A data-shaped key does not qualify.

So a mirrored, data-shaped key whose zod face admits MORE than its TS face falls between all four — the same between-the-ledgers shape objectui#6881 recorded for the read-nowhere axis, one axis over.

Measured instances of the direction (it recurs; this is not a one-off)

  • DataTableSchema.toolbar — TS said SchemaNode[]; the mirror admitted a single node OR an array. Measured on objectui#6881, invisible to all four ledgers (grep for the key in the parity file: zero hits). The instance died with the retirement (PR feat(types)!: retire DataTableSchema.toolbar — declared everywhere, read nowhere (objectui#6881) #7066 refuses both spellings), the class did not.
  • TableColumn.type — interface declared 8 literals, mirror accepted any string (objectui#5853, closed per-key). Same inequality, found by hand, not by a ledger.
  • DataTableSchema.rowActions — mirror declares an array while the TS declaration and every reader treat it as a boolean (objectui#6940, open) — disjoint rather than strictly wider, but the same "mirror admits what TS refuses" reading on one side.

The producing pattern is systematic: z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]) appears at 12+ mirror sites (base.zod.ts body/children, blocks.zod.ts defaultContent/template/slotContent, complex.zod.ts content, crud.zod.ts dialog content, ...). Whether each TS twin spells the same union or only the array has never been audited in this direction — every audit so far ran the other way.

Why the direction matters (not symmetric cosmetics)

The zod mirror is the AUTHORING boundary — it is what validates AI-written metadata. A mirror-wider key hands an author a green parse on a spelling the type system refuses, so the two published faces disagree about the accept-set and the runtime reader gets input the TS face says cannot exist. objectui#6881's single-node toolbar was exactly this: green through safeParse, refused by tsc, mounted by nothing. The precedent that a direction-blindness finding is card-worthy — and that the remedy is a new ledger rather than per-key whack-a-mole — is objectui#6058, which recorded the unmirrored direction's blindness and produced UnmirroredDeclared.

Dedup

One targeted semantic search (search_issues, scoped to this repo) over the parity/mirror vocabulary returned 11 substantive results — a live instrument, not a silent zero. Reviewed all 11: objectui#6058 / #6152 cover the UNMIRRORED direction, #5927 / #6033 the mirror-NARROWER direction, #5853 / #6638 / #6940 are per-key instance cards, #6141 is a prose-vs-registry count drift. No card claims the class-level gap for the wider direction. Channel note, declared: the repo-scoped REST list endpoint is not usable from this seat (calls are refused by the session's permission layer), so the dedup ran on the semantic search channel instead of REST-plus-local-regex.

Related

  • objectui#6881 — the card whose triage recorded this rider; its PM comment carries the instruction discharged here.
  • PR feat(types)!: retire DataTableSchema.toolbar — declared everywhere, read nowhere (objectui#6881) #7066 — retires the toolbar instance; this card exists so the class does not evaporate with it (the objectstack#13306 shape).
  • objectui#6058 — the same finding for the unmirrored direction, and the precedent for what a remedy looks like.
  • objectui#6152 — the unmirrored ledger's debt; different family, listed to prevent re-conflation.

Activity

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

Metadata

Metadata

Assignees

Labels

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions