Skip to content

spec(types): derive and export the strict authoring twin of the node face — the #5250 strict face itself, no consumer wired #8345

Description

@claude

Priced by the domain:spec @ objectui seat on #7935. ⛔ Filed unassigned, not claiming.

Blocked-by: #8344

This is the strict face itself, as ruled on #5250 (director comment 5534418546, maintainer 2026-09-04, decision batch #25, option 2): "each node schema gets a derived strict variant; objectui validate and the doc-snippet gates run strict; renderer props keep the tolerant face unchanged". ⛔ The rendering face's .passthrough() is not flipped — the programme adds a face, it does not change the existing one.

Scope

Export a derived strict twin of the node face from @object-ui/types/zod. Derived, not hand-written: a second hand-maintained copy of 107 component schemas is a parity ledger nobody can keep honest, and this repo already carries the evidence of what that costs (#6058, #6152, #7759).

No consumer is wired by this card. objectui validate and the JSON-fence gate are the devx seat's half, priced on #5250 once this exists; the ruling is explicit that the fence gate is built on top of the strict face, not before it.

Why the derivation is the cheap half — it is already prototyped and measured

scripts/measure-strict-authoring-face.mjs (landed on main by PR #7916) contains a working derivation, and #7581's report records its coverage as a measurement rather than a claim:

  • Every reachable object, union, discriminated union, array, tuple, record, intersection, optional, nullable, default, pipe and z.lazy is strict-ified.
  • Shapes strict could not close: only opaque custom / function / transform validators — there is no shape inside them to close. That is the complete limit list, not a sample.
  • Registry collisions: 0. Arms without a literal type: 0.
  • Objects are cloned by patching _zod.def and calling their own constructor, ⛔ not rebuilt with z.object(shape) — the latter drops .refine() checks, and a twin that quietly lost a refinement under-reports red.

⇒ The engineering risk in this card is the export surface and its pins, not the walker.

The number this card is accountable for

Measured at origin/main 5505aec1a07c26976d160a39f152a48b088cfbb4 (zod 4.4.3), over 553 catalog + docs node documents:

reading documents refused
the face as shipped 45 / 553
redirect + strict — this card's end state 176 / 553

Per component, judging each node against its own schema (2099 nodes at the same commit): 184 refused, of which 129 are green today and red only under strict and 55 are already red under the face as shipped. 60 of the 94 component types seen are strict-CLEAN — zero refusals.

⚠️ The 176 is not this card's repair budget. This card ships the face; it does not repair a single document. The refusals become actionable only when a consumer is wired, which is deliberately a different card.

⚠️ Every figure above moved between the two commits it has been measured on, which is why they carry pins: at fa7d66c45 the same script read 196 refused / 137 strict-only / 59 red-today / 58 clean over 2100 nodes and 557 documents. Nothing in #6939 moved them — its eight declaration-repair groups had all landed before either reading (PRs #7456, #7471, #7533, #7541, #7545, #7560; confirmed on that card 2026-09-03T22:21:48Z). ⇒ re-derive before quoting, ⛔ do not inherit a number from this body.

Appetite — one dispatched card, one PR

In scope: the derivation, its export from @object-ui/types/zod, and pins that (a) a known-good document parses, (b) a document with one invented top-level key is refused with unrecognized_keys naming that key, (c) the tolerant face is byte-for-byte unchanged in behaviour on the same inputs.

⛔ Falls off the back rather than growing this card:

Grading notes

Refs: #5250 (the ruling) · #7935 (this pricing) · #7581 / PR #7916 (the measurement and the prototype derivation) · #7917 (2 arms the zod face never exports by name) · #6939


Generated by Claude Code

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions