…dar-view renderer's read set
Fixes#5667 (maintainer ruling: option A, renderer authoritative, scoped by
measurement).
Retires the nine inert keys (events — required-but-dropped per #4433 —
defaultView, defaultDate, date, views, editable, onEventCreate, onEventUpdate,
onDateChange), declares the measured read set (data, titleField,
startDateField, endDateField, allDayField, colorField, view, currentDate,
allowCreate, className) plus the two host-only hatches the renderer forwards
(onEventClick, onViewChange). Zod mirror moves in the same change; the
plugin-calendar README and content/docs/api/schema-reference.md are repaired
so no copy of the old contradiction survives.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E7snar5mwF7qoXJazqKhys
Fixes#5667
Maintainer ruling (2026-08-22, recorded on the issue): Option A — the renderer is authoritative;
CalendarViewSchemaconverges on the measured read set, liveness measurement first, docs repaired in the same PR.Liveness measurement (taken on the authored-node path, not by key-name grep)
The
calendar-viewregistry renderer (packages/plugin-calendar/src/calendar-view-renderer.tsx) reads, per its own source:schema.data+titleField/startDateField/endDateField/allDayField/colorField(event computation, lines ~270-295),view(resolveAuthoredView),currentDate(resolveAuthoredCurrentDate),allowCreate(resolveAuthoredAllowCreate),className(forwarded), plus the function-typed host hatches (HOST_CALLBACKS, incl.onEventClick/onViewChange). An authoredeventsis destructured out as_authoredEventsand dropped (#4433). The registryinputsblock (lines 397-469) declares exactly the ten keys the ruling lists.Authored instances of the nine inert keys on
calendar-viewnodes: zero — sweptapps,examples,e2e,packages,contentin this repo (the only real authored nodes,examples/schema-catalog/src/schemas/plugin-calendar/*.json, author exactly the converged set) and theobjectstacktree's example apps (nocalendar-viewnode exists there at all). So the ruling's qualifier "retire only what no app authors" permits retiring all nine.Change
packages/types/src/complex.ts—CalendarViewSchemaretiresevents(was the only required key besidestype),defaultView,defaultDate,date,views,editable,onEventCreate,onEventUpdate,onDateChange; declaresdata, the five field-name keys,view,currentDate,allowCreate,className, and keeps the two host-only hatches the renderer actually forwards (onEventClick,onViewChange), documented as host-only.packages/types/src/zod/complex.zod.ts— mirror moves in the same stroke. Measured: zodBaseSchemais.passthrough(), so retirement does not create rejections; the material accept change is thateventsstops being required.content/docs/api/schema-reference.md— theCalendarViewSchemasection's example and property table rewritten to the converged surface (the old table publishedonDateChangeet al. as working callbacks; the old example authoreddefaultView/views/editable/events).packages/plugin-calendar/README.md— Schema API fence, "Basic Calendar" / "Interactive Calendar" / "Customization" / registration / TypeScript-Support examples all repaired (five separateevents:-authoring instances); the "type is not the renderer" contradiction note replaced by the converged statement. Thereadme-calendar-view-schema.test.tspin (parses both the interface and the fence from source) holds the two together and passes..changeset/calendar-view-schema-converge.md—@object-ui/typesminor (repo policy: breaking ships as minor with the semantics stated in the body; the fixed group's major tracks@objectstack),@object-ui/plugin-calendarpatch.Runtime renderer behaviour is unchanged; the #4433 events-drop pin (
calendar-view-renderer.eventsCollision.test.tsx) still passes and is still falsifiable (it pins renderer behaviour, which this PR does not touch).Measured breaking radius
BaseSchema(TS) carries[key: string]: any— so literals still authoring retired keys keep compiling, and reads of them degrade toany; the compile-level break is limited to annotations that relied oneventsbeing required, plus value-level checks on the newly declared keys (e.g.titleField: 42is now an error — see reverse verification). zod-side, nodes withouteventsnow validate; wrong-typed retired keys (e.g.editable: 'yes') are no longer rejected. Out-of-repo annotation use is unmeasurable from here (triage's own confidence gap; stated, not asserted).Verification (all at
47c00a5, the head of this PR)pnpm exec vitest run packages/types/ packages/plugin-calendar/— 54 files / 557 tests passed (includes the plugin-calendar: authoringeventson acalendar-viewnode crashes the component — the SDUI action object overwrites the computed CalendarEvent array #4433 pin, the README-schema pin, inertInputs/propsContract/currentDate suites, and the types zod/parity suites). Re-run at the final commit.pnpm --filter @object-ui/types buildthen dist proof:titleFieldpresent indist/complex.d.ts, zero occurrences of the retired requiredevents: CalendarEvent.{ type: 'calendar-view', titleField: 42 }→ red (TS2322: Type 'number' is not assignable to type 'string'— old dist accepted it via the index signature);{ type: 'calendar-view' }→ compiles (old dist rejected it for missingevents). One error, exactly the expected one, in each direction.pnpm --filter @object-ui/types type-check✓;pnpm --filter '@object-ui/plugin-calendar^...' build+pnpm --filter @object-ui/plugin-calendar type-check✓.check:doc-types("Every documented component type is registered"),check:doc-snippets("Every covered documentation snippet compiles against the built types" — 88/88),check:spec-symbols,check:i18n-keys,check:i18n-drift,check:published-dist("No published package's build output carries tooling material"),check:phantom-deps,check:self-import,check:esm-specifiers,check:node-esm-load,check:action-forward-parity,check:control-bytes,docs:check-links("Links are valid across 13 scan roots"),pnpm check(CLI schema validation, "All checks passed"), changeset presence / fixed / no-major.turbo run lint --filter=@object-ui/types --filter=@object-ui/plugin-calendar✓ (3/3 tasks). Declared narrowing vs the full-farmpnpm lint: objectui lint is per-package eslint and the rooteslint.config.jsenables no type-aware linting (projectService/parserOptions.projectabsent), so untouched packages' lint verdicts cannot be moved by this diff; both touched packages were linted in full. Full-farm lint, the 4-shard test farm, the performance budget, and external-link lychee are CI's runs.Generated by Claude Code
Generated by Claude Code