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
Filed unassigned, no pm:* label — triage owns grading and routing. Recorded by the domain:devx @ objectui execution seat (#5748), PM session session_019b5UBNMtTzKbVtZZGvFuxe, from the handback of #6058 (PR #6149).
What this is
#6058 fixed a blind guard: zod-mirror-parity's forward comparison mapped over the intersection of mirrored keys and keyof the declaration, so a key declared on the TypeScript side and absent from the mirror did not compare unequal — it left the comparison entirely. PR #6149 lands the union comparison and seeds a second, separately-ratcheted ledger, UnmirroredDeclared, at the measured debt.
⛔ This card is that debt. It is not a defect in the guard and not a regression — every fact below was already true; nothing was watching. KnownDrift and NarrowerThanDeclared are untouched at 12 entries / 17 keys, and #5927 / PR #6032's citable 17 → 13 shrink stays comparable.
16 pairs carry 121 declared-but-unmirrored keys, out of 158 registered pairs. Each one is a key the published TypeScript invites an author to write and the published validator has never heard of — the "declared ≠ enforced" shape this whole family exists to close.
⚠️ Note on the arithmetic, because two different counts are in circulation: #6058's round-1 report counted 23 red pairs under the union comparison, of which 7 were red only via their pre-existing KnownDrift entries. The 16 here are the pairs that actually carry unmirrored keys. The earlier 4-vs-19 spec split maps to 3-vs-13 below because PageNodeSchema's redness is entirely KnownDrift and it contributes zero unmirrored keys.
Spec-derived — ⛔ route to #2231, do not fix locally (3 pairs, 14 keys)
On these the mirror takes its shape by reference from @objectstack/spec, so an unmirrored declared key means the local declaration carries members the spec schema does not model. That is the unification question, not a local mirror edit — and SPEC_DERIVED_PAIRS' own doc notes a spec bump legitimately moves these sets. They are marked in the ledger rather than exempted in the instrument.
Three were verified by hand against both sources during #6058, as a spot-check that these are defects rather than instrument noise: InputSchema.wrapperClass (declared in src/form.ts, absent from the mirror), DetailViewSectionSchema.hideEmpty, ChartSchema.drillDown.
⭐ The sorting that should come before any batching — 23 of the 121 are callback-shaped
23 keys are on* props: 12 on DataTableSchema, 5 on ObjectFormSchema, 3 on DetailViewSchema, and 1 each on FormSchema, ObjectGridSchema, ObjectViewSchema.
⚠️ For those, "mirror it" may be the wrong remedy. The right one may be to narrow the declaration so it stops advertising a runtime callback as authorable metadata — which shrinks the ledger without touching any mirror, and is a scope reduction. objectui#4453 already picked that direction once, narrowing to typeof === 'function' so an authored string handler is dropped; and #6122 / PR #6142 landed the documentation half of the same judgement an hour ago, after measuring that no renderer reads any of 16 schema-level event slots.
⛔ So this subset is worth one ruling covering all 23, not 23 per-key decisions and not a blanket mirroring sweep. Deciding it first also shrinks whatever remains.
What a taker needs to know
⛔ Growing KnownDrift is not the remedy for anything here — that ledger means "mirrors that refuse a declared spelling" and is a different, honest 12. UnmirroredDeclared is the ledger these belong to, and it is shrink-only: any new declared-but-unmirrored key on any of the 158 pairs reddens immediately, so the debt cannot grow while it is worked off.
The ledger is pinned in both directions by ReconcileAgainstLedger with synthetic-pair tests, so a fact deleted from the seed is not silently re-acceptable and a stale entry names itself.
The measurement instrument is the TypeScript compiler API walking each pair's union members via isStringLiteral().value; its non-vacuity control is that it read all 158 pairs and returned empty for 142.
Refs: #6058 / PR #6149 (where this was measured and where the ledger lands) · #6141 (the stale 163/13 prose, corrected by that PR) · #5927 / PR #6032 (the 17 → 13 shrink this preserves) · #2231 (spec unification, where the 3 spec-derived pairs go) · #5155 (what an index signature does and does not cap) · #4453 / #6122 (the callback-narrowing precedent).
Filed unassigned, no
pm:*label — triage owns grading and routing. Recorded by thedomain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe, from the handback of #6058 (PR #6149).What this is
#6058 fixed a blind guard:
zod-mirror-parity's forward comparison mapped over the intersection of mirrored keys andkeyofthe declaration, so a key declared on the TypeScript side and absent from the mirror did not compare unequal — it left the comparison entirely. PR #6149 lands the union comparison and seeds a second, separately-ratcheted ledger,UnmirroredDeclared, at the measured debt.⛔ This card is that debt. It is not a defect in the guard and not a regression — every fact below was already true; nothing was watching.
KnownDriftandNarrowerThanDeclaredare untouched at 12 entries / 17 keys, and #5927 / PR #6032's citable 17 → 13 shrink stays comparable.16 pairs carry 121 declared-but-unmirrored keys, out of 158 registered pairs. Each one is a key the published TypeScript invites an author to write and the published validator has never heard of — the "declared ≠ enforced" shape this whole family exists to close.
KnownDriftentries. The 16 here are the pairs that actually carry unmirrored keys. The earlier 4-vs-19 spec split maps to 3-vs-13 below becausePageNodeSchema's redness is entirelyKnownDriftand it contributes zero unmirrored keys.Spec-derived — ⛔ route to #2231, do not fix locally (3 pairs, 14 keys)
On these the mirror takes its shape by reference from
@objectstack/spec, so an unmirrored declared key means the local declaration carries members the spec schema does not model. That is the unification question, not a local mirror edit — andSPEC_DERIVED_PAIRS' own doc notes a spec bump legitimately moves these sets. They are marked in the ledger rather than exempted in the instrument.complex.zod.ts#DashboardComponentSchematitlecomplex.zod.ts#DashboardWidgetSchemapagination,searchableobjectql.zod.ts#ObjectViewSchemaallowCreateView,defaultListView,defaultViewType,filterableFields,listViews,navigation,onNavigate,searchableFields,showViewSwitcher,viewActions,viewTabBarLocal mirror omissions (13 pairs, 107 keys)
objectql.zod.ts#ObjectFormSchemaallowSkip,buttons,defaultTab,defaults,drawerSide,drawerWidth,formType,mobile,modalCloseButton,modalSize,nextText,onCancel,onError,onOpenChange,onStepChange,onSuccess,open,prevText,sections,showStepIndicator,splitDirection,splitResizable,splitSize,subforms,submitHandler,tabPositiondata-display.zod.ts#DataTableSchemadisableInnerScroll,editable,manualPagination,manualSearch,manualSorting,onAddRecord,onBatchSave,onCellChange,onColumnReorder,onColumnResize,onPageChange,onPageSizeChange,onRowActionDef,onRowClick,onRowSave,onSearchChange,onSortChange,page,rowActionDefs,rowClassName,rowCount,rowStyle,search,selectionResetKey,selectionStyle,showAddRow,showSelectionCount,singleClickEdit,sortobjectql.zod.ts#ObjectGridSchemaaggregations,bulkActionDefs,bulkSpecActions,conditionalFormatting,emptyState,exportOptions,grouping,navigation,onNavigate,operations,reorderableColumns,resizableColumns,rowColor,rowHeight,rowSpecActions,singleClickEdit,titleviews.zod.ts#DetailViewSchemaactivities,autoDiscoverRelated,autoTabs,comments,defaultTab,highlightFields,history,onAddComment,onNavigate,onTabChange,primaryField,recordNavigation,sectionGroups,summaryFieldsform.zod.ts#FormSchemadefaultFieldTab,fieldContainerClass,fieldPanes,fieldPanesOrientation,fieldPanesResizable,fieldTabs,fieldTabsPosition,mobileStickyActions,onDirtyChangecomplex.zod.ts#ChatbotSchemadisplayMode,floatingConfig,requestBodyreports.zod.ts#ReportComponentSchemachartConfig,conditionalFormatting,reportTypedata-display.zod.ts#ChartSchemadrillDownform.zod.ts#FormFieldSchemafieldform.zod.ts#InputSchemawrapperClassform.zod.ts#LabelSchemacontentnavigation.zod.ts#PaginationSchemacurrentPageviews.zod.ts#DetailViewSectionSchemahideEmptyThree were verified by hand against both sources during #6058, as a spot-check that these are defects rather than instrument noise:
InputSchema.wrapperClass(declared insrc/form.ts, absent from the mirror),DetailViewSectionSchema.hideEmpty,ChartSchema.drillDown.⭐ The sorting that should come before any batching — 23 of the 121 are callback-shaped
23 keys are
on*props: 12 onDataTableSchema, 5 onObjectFormSchema, 3 onDetailViewSchema, and 1 each onFormSchema,ObjectGridSchema,ObjectViewSchema.typeof === 'function'so an authored string handler is dropped; and #6122 / PR #6142 landed the documentation half of the same judgement an hour ago, after measuring that no renderer reads any of 16 schema-level event slots.⛔ So this subset is worth one ruling covering all 23, not 23 per-key decisions and not a blanket mirroring sweep. Deciding it first also shrinks whatever remains.
What a taker needs to know
KnownDriftis not the remedy for anything here — that ledger means "mirrors that refuse a declared spelling" and is a different, honest 12.UnmirroredDeclaredis the ledger these belong to, and it is shrink-only: any new declared-but-unmirrored key on any of the 158 pairs reddens immediately, so the debt cannot grow while it is worked off.ReconcileAgainstLedgerwith synthetic-pair tests, so a fact deleted from the seed is not silently re-acceptable and a stale entry names itself.--noErrorTruncationwill not show you the whole list through a named alias — TS prints the alias name and elaborates exactly one member with no ellipsis. finding: the #5684 zod-mirror-parity guard is BLIND to a key declared on the TS side but absent from the mirror — measured on ObjectGanttSchema, and it is the guard #5927 just used as authoritative #6058 measured that an inline spelling resolves the union and prints a real... N more ..., and wrote both readings into the file. Read the ledger, not the compiler error, to see the set.isStringLiteral().value; its non-vacuity control is that it read all 158 pairs and returned empty for 142.Refs: #6058 / PR #6149 (where this was measured and where the ledger lands) · #6141 (the stale 163/13 prose, corrected by that PR) · #5927 / PR #6032 (the 17 → 13 shrink this preserves) · #2231 (spec unification, where the 3 spec-derived pairs go) · #5155 (what an index signature does and does not cap) · #4453 / #6122 (the callback-narrowing precedent).