You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
finding(types): 57 ZodDefault nodes still reachable from the published @object-ui/types/zod barrel after #7735 — batch #69's principle stops at the files it named, and the rest are imported by reference from @objectstack/spec #8317
Observation-class finding, measured by the objectui#7735 developer session and escalated by that PR's contract review. Filed unassigned, no labels — grading is the triage seat's. ⛔ This is a ruling question, not a defect with an obvious repair.
The claim
Decision batch #69 (2026-09-07, maintainer 「其他同意」) ruled, on objectui#7735:
A validator validates; it does not write values into an author's document.
PR #8299 delivers that for the 41 .default() call sites written in this repo's own mirrors. It does not — and under its ruling's named scope could not — reach the defaults this repo's published barrel re-exports from elsewhere.
After #8299, 57 ZodDefault nodes remain reachable from @object-ui/types/zod, every one inside a subschema imported by reference from @objectstack/spec. So safeValidateSchema still substitutes values into a parsed document, on those keys, exactly as the ruling says a validator should not.
Four keys the author did not write, present in result.data. The affected families named by the measuring session: app.active / isDefault · object-view.navigation.{mode, preventNavigation, openNewTab, size} · list-view.sharing.type · kanban.grouping.fields[].{order, collapsed} · page.interfaceConfig.* · dashboard chartConfig.*.
⇒ The "one authored document, two shapes" defect objectui#7735 was opened about survives on these keys. The graph delta is the same instrument that priced #8299: 98 ZodDefault nodes on its base, 57 on its head — the 41 it removed are exactly the difference.
⭐ Why this is a ruling and not a port — two measurements that set the price
1. The upstream population is two orders of magnitude larger. Measured on objectstack-ai/objectstackorigin/main = f2f6684, real .default() call sites (docblock mentions excluded):
⇒ Extending batch #69 to the spec face is a 1546-site question with its own consumers, its own release train and its own authoring story — ⛔ not a 57-site follow-up, and ⛔ not something to infer from a ruling written about this repo's mirrors.
2. The cheap route already exists here and has been used once.packages/types/src/zod/objectql.zod.ts:452 on origin/main = 8f9d87a:
⇒ Stripping an imported default at this repo's boundary is an established local pattern, not an invention. Whether it should be applied to 57 more sites — and whether doing so silently diverges this repo's parse output from the upstream contract it mirrors — is the question.
The fork, stated so nobody has to reconstruct it
(a) Strip at this repo's import boundary (.removeDefault(), ×57). Cheap, local, keeps batch Redesign examples based on new JSON project specification #69's principle whole for objectui consumers. ⚠️ Cost: this repo's parse output then differs from @objectstack/spec's own, on keys it claims to mirror — a new divergence in a package whose whole job is not to diverge.
(b) Raise it upstream as a spec-side ruling. Principled and one answer for everyone. ⚠️ Cost: 1546 sites, another repo's release train, and a decision that is not this seat's to make.
(c) Rule the boundary explicitly: the mirror stops authoring defaults, imported subschemas keep theirs, and that asymmetry is written down rather than left to be rediscovered. ⚠️ Cost: safeValidateSchema keeps two behaviours and an author cannot tell which key is which without reading the import graph.
⛔ This card picks none. ⚠️ What it argues is that (c) by default and unstated — which is what lands if nobody rules — is the one outcome with no defender, because it leaves batch #69's principle true of some keys and false of others with nothing saying where the line is.
objectui#4631 — the standing "three declared surfaces disagree" card, pm:on-hold.
The measuring session recorded this as noted, not filed and deferred the decision to the seat, which was right: it is another repo's surface on one route and a contract divergence on the other.
Filed by the domain:spec @ objectui PM seat, session session_01QtGhnU3WnnWyiWeYQhw2aX, 2026-09-07T11:15Z.
Observation-class finding, measured by the objectui#7735 developer session and escalated by that PR's contract review. Filed unassigned, no labels — grading is the triage seat's. ⛔ This is a ruling question, not a defect with an obvious repair.
The claim
Decision batch #69 (2026-09-07, maintainer 「其他同意」) ruled, on objectui#7735:
PR #8299 delivers that for the 41
.default()call sites written in this repo's own mirrors. It does not — and under its ruling's named scope could not — reach the defaults this repo's published barrel re-exports from elsewhere.After #8299, 57
ZodDefaultnodes remain reachable from@object-ui/types/zod, every one inside a subschema imported by reference from@objectstack/spec. SosafeValidateSchemastill substitutes values into a parsed document, on those keys, exactly as the ruling says a validator should not.Reproducer
Four keys the author did not write, present in
result.data. The affected families named by the measuring session:app.active/isDefault·object-view.navigation.{mode, preventNavigation, openNewTab, size}·list-view.sharing.type·kanban.grouping.fields[].{order, collapsed}·page.interfaceConfig.*· dashboardchartConfig.*.⇒ The "one authored document, two shapes" defect objectui#7735 was opened about survives on these keys. The graph delta is the same instrument that priced #8299: 98
ZodDefaultnodes on its base, 57 on its head — the 41 it removed are exactly the difference.⭐ Why this is a ruling and not a port — two measurements that set the price
1. The upstream population is two orders of magnitude larger. Measured on
objectstack-ai/objectstackorigin/main=f2f6684, real.default()call sites (docblock mentions excluded):packages/spec/src/**(whole package)packages/spec/src/ui/**onlyview.zod.ts41,component.zod.ts38,chart.zod.ts11,app.zod.ts10,page.zod.ts7,dashboard.zod.ts6,action.zod.ts5,report.zod.ts4,sharing.zod.ts2,widget.zod.ts2⇒ Extending batch #69 to the spec face is a 1546-site question with its own consumers, its own release train and its own authoring story — ⛔ not a 57-site follow-up, and ⛔ not something to infer from a ruling written about this repo's mirrors.
2. The cheap route already exists here and has been used once.
packages/types/src/zod/objectql.zod.ts:452onorigin/main=8f9d87a:⇒ Stripping an imported default at this repo's boundary is an established local pattern, not an invention. Whether it should be applied to 57 more sites — and whether doing so silently diverges this repo's parse output from the upstream contract it mirrors — is the question.
The fork, stated so nobody has to reconstruct it
.removeDefault(), ×57). Cheap, local, keeps batch Redesign examples based on new JSON project specification #69's principle whole for objectui consumers.@objectstack/spec's own, on keys it claims to mirror — a new divergence in a package whose whole job is not to diverge.safeValidateSchemakeeps two behaviours and an author cannot tell which key is which without reading the import graph.⛔ This card picks none.⚠️ What it argues is that (c) by default and unstated — which is what lands if nobody rules — is the one outcome with no defender, because it leaves batch #69's principle true of some keys and false of others with nothing saying where the line is.
Refs
.default()values the renderers never apply — a parsedcontainerrenders a different width than an unparsed one #7735 (comment)pm:on-hold.noted, not filedand deferred the decision to the seat, which was right: it is another repo's surface on one route and a contract divergence on the other.Filed by the
domain:spec @ objectuiPM seat, sessionsession_01QtGhnU3WnnWyiWeYQhw2aX, 2026-09-07T11:15Z.Generated with Claude Code
https://claude.ai/code/session_01QtGhnU3WnnWyiWeYQhw2aX