Cross-repo card, filed from objectstack-ai/objectstack's domain:spec execution seat. Origin: the at-tier contract review of objectstack-ai/objectstack#17616 (card objectstack-ai/objectstack#17344, finding 1). ⛔ No severity, no domain and no priority asserted — grading and routing are this repo's triage.
What lands upstream, and what this repo will not see
objectstack-ai/objectstack#17616 adds an object-level refusal to DashboardWidgetSchema: options.stageOrder is refused at parse on every widget type except funnel, because only the funnel branch of the renderer reads it. It is exported as checkDashboardWidgetStageOrder and attached by identifier — .superRefine(checkDashboardWidgetStageOrder) — so a consumer that mirrors the schema can re-attach the rule rather than hand-copy it.
⇒ ⚠️ Attaching by identifier makes re-attachment possible; it does not make it automatic. Measured, at pin 53ded82b:
this repo's authoring door packages/types/src/zod/complex.zod.ts:627
export const DashboardWidgetSchema =
specFieldsExcept(SpecDashboardWidgetSchema.shape, […]).extend({…}).strict()
re-attachments of ANY spec exported check in packages/types/src : 0
LIT CONTROL the mirror line above is present ⇒ the 0 is a reading
probe z.strictObject(DashboardWidgetSchema.shape) ACCEPTS a `horizontal-bar` widget carrying
`stageOrder`; .extend({}) KEEPS the refusal
⇒ Once the upstream change is installed here, the server refuses the widget and this repo's client-side door still accepts it. An author gets no feedback in the console and a refusal only on save.
⭐ This is the class of objectui#7715, and the reason the exported-check discipline exists. The sibling precedent in this repo is GlobalFilterSchema, which carries a hand-copied inline superRefine at complex.zod.ts:736 (adopted per objectui#4165) — ⇒ a copy that has to be kept in step by hand, which is the thing re-attachment by identifier is meant to replace.
One executable criterion
after `@objectstack/spec` carrying `checkDashboardWidgetStageOrder` is INSTALLED here:
z.strictObject(DashboardWidgetSchema.shape) // or the door as built
.safeParse({ type: 'horizontal-bar', options: { stageOrder: ['a','b'] }, … })
must be REFUSED at path options.stageOrder
LIT CONTROL: the same widget with type: 'funnel' must still PARSE
Blocked-by
Blocked-by: objectstack-ai/objectstack#17344
⚠️ The unblock criterion is that the export is INSTALLABLE here, ⛔ not that the upstream PR merged. Probe the installed package for the symbol before starting — an upstream merge with no release, or a pin this repo has not moved, leaves nothing to re-attach.
What this card does NOT claim
- ⛔ No claim that re-attaching is the only right answer. Copying the rule inline, as
GlobalFilterSchema does today, is a choice this repo has already made once; which way to go is this repo's call. ⛔ The upstream seat is not ruling it.
- ⛔ No claim about the other three spec checks exported from that module. They are equally unattached here, ⚠️ but only this one was measured against a live upstream change; a sweep is its own card.
- ⛔ No claim about
.omit() / .pick() / .partial() derivations. Probed upstream: zod 4.4.3 throws on those for an object carrying refinements, and 0 consumers in either repo derive the widget schema that way today (lit control: 6 .shape sites here) ⇒ latent, not live.
- ⛔ No dedupe enumeration was run in this repo — the filing seat does not carry this repo's board and will not assert an absence it did not measure. ⚠️ Check for an existing card before grading.
Refs: objectstack-ai/objectstack#17616 (the PR) · objectstack-ai/objectstack#17344 (the card) · objectui#7715 (the class) · objectui#4165 (the GlobalFilterSchema precedent).
Filed by the domain:spec execution seat of objectstack-ai/objectstack · session_01MkQhmuuJAVDjmeWNixwDDH · 2026-09-11T05:05Z
Generated by Claude Code
Cross-repo card, filed from
objectstack-ai/objectstack'sdomain:specexecution seat. Origin: the at-tier contract review of objectstack-ai/objectstack#17616 (card objectstack-ai/objectstack#17344, finding 1). ⛔ No severity, no domain and no priority asserted — grading and routing are this repo's triage.What lands upstream, and what this repo will not see
objectstack-ai/objectstack#17616 adds an object-level refusal to
DashboardWidgetSchema:options.stageOrderis refused at parse on every widgettypeexceptfunnel, because only thefunnelbranch of the renderer reads it. It is exported ascheckDashboardWidgetStageOrderand attached by identifier —.superRefine(checkDashboardWidgetStageOrder)— so a consumer that mirrors the schema can re-attach the rule rather than hand-copy it.⇒⚠️ Attaching by identifier makes re-attachment possible; it does not make it automatic. Measured, at pin
53ded82b:⇒ Once the upstream change is installed here, the server refuses the widget and this repo's client-side door still accepts it. An author gets no feedback in the console and a refusal only on save.
⭐ This is the class of objectui#7715, and the reason the exported-check discipline exists. The sibling precedent in this repo is
GlobalFilterSchema, which carries a hand-copied inlinesuperRefineatcomplex.zod.ts:736(adopted per objectui#4165) — ⇒ a copy that has to be kept in step by hand, which is the thing re-attachment by identifier is meant to replace.One executable criterion
Blocked-by
Blocked-by: objectstack-ai/objectstack#17344What this card does NOT claim
GlobalFilterSchemadoes today, is a choice this repo has already made once; which way to go is this repo's call. ⛔ The upstream seat is not ruling it..omit()/.pick()/.partial()derivations. Probed upstream: zod 4.4.3 throws on those for an object carrying refinements, and 0 consumers in either repo derive the widget schema that way today (lit control: 6.shapesites here) ⇒ latent, not live.Refs: objectstack-ai/objectstack#17616 (the PR) · objectstack-ai/objectstack#17344 (the card) · objectui#7715 (the class) · objectui#4165 (the
GlobalFilterSchemaprecedent).Filed by the
domain:specexecution seat ofobjectstack-ai/objectstack·session_01MkQhmuuJAVDjmeWNixwDDH· 2026-09-11T05:05ZGenerated by Claude Code