Skip to content

feat(types): retire 'agenda' from CalendarViewMode and the zod enum - #5782

Merged
os-sam merged 1 commit into
mainfrom
claude/issue-5740-calendar-view-mode-agenda
Aug 23, 2026
Merged

feat(types): retire 'agenda' from CalendarViewMode and the zod enum#5782
os-sam merged 1 commit into
mainfrom
claude/issue-5740-calendar-view-mode-agenda

Conversation

@os-sam

Copy link
Copy Markdown
Collaborator

Fixes#5740

Direction

Option A — narrow the value union — inherited from the maintainer's 2026-08-22 ruling on #5667 ("the renderer is authoritative; CalendarViewSchema converges on the measured read set"), of which this card is the value-level residue on the same renderer. Recorded in the claim comment on #5740 as a veto window; both stop conditions were re-measured and hold (below). Not a fresh adjudication.

What changed

  • CalendarViewMode (packages/types/src/complex.ts) is now 'month' | 'week' | 'day'; CalendarViewModeSchema (packages/types/src/zod/complex.zod.ts) is now z.enum(['month', 'week', 'day']).
  • Docblocks on both faces, the zod describe on view, and the CalendarViewSchema table row in content/docs/api/schema-reference.md no longer teach an 'agenda' fallback.
  • New pin: packages/types/src/__tests__/calendar-view-mode-agenda-retired.test.ts (modeled on owner-retired-contract-twins.test.ts) — refusal envelope (invalid_value on the view path, offered vocabulary asserted), full-green survivors, passthrough control, @ts-expect-error TS twin (enforced via tsconfig.test.json chained from type-check).
  • Changeset: minor for @object-ui/types (majors track @objectstack), body states the breaking semantics.
  • Unchanged on purpose:resolveAuthoredView and the registry input (enum: ['month','week','day'] already declared) — the runtime boundary still resolves any off-union value in raw metadata to the 'month' default, and calendar-view-renderer.propsContract.test.tsx's off-enum fixture still pins that branch (it authors view: 'agenda' through an as never cast; after this change that value is simply another off-enum spelling, which is exactly what the fixture represents).

⚠️ This narrows the accept set

Unlike #5667's key retirements (no new rejections under .passthrough()), view is a declared key and declared keys are validated even under .passthrough(). Measured on this tree before the change: CalendarViewSchema.safeParse({type:'calendar-view', view:'agenda'})success: true. After: success: false, exactly one invalid_value issue on the view path offering month/week/day. Undeclared keys still pass (pinned by the passthrough control test). Clause-② dispatch at tier per the claim comment; no compensating label exists in this repo.

Measurements (stop conditions and reachability)

  • Zero authors of view: 'agenda': swept objectui (all file types, including examples/, catalog, docs) and the full objectstack tree — the only occurrences are the declarations themselves and the props-contract fixture that pins the off-enum drop branch. Stop condition 1 holds.
  • Parent's reason is general, not branch-specific: the renderer's registered input declares ['month','week','day'] (calendar-view-renderer.tsx:451), resolveAuthoredView drops off-enum values (:115), CalendarView's own prop and switcher are three-valued, ObjectCalendar reads defaultView as three-valued. Stop condition 2 holds.
  • CalendarViewMode reachability: consumers are CalendarViewSchema.view and the HOST-ONLY onViewChange parameter — both on this same renderer contract; no other package imports the symbol (narrowing a callback parameter is contravariance-safe for hosts). CalendarViewModeSchema's only consumer is the view key. The defaultView enums in objectql.ts / objectql.zod.ts are textually independent inline unions, not consumers — same defect class on a different declaration, filed separately rather than smuggled in here.

File surface note

The claim's file surface was packages/types/src/complex.ts, packages/types/src/zod/complex.zod.ts, packages/plugin-calendar/**, changeset. This PR additionally touches one row of content/docs/api/schema-reference.md (line ~1079) — the docs-table copy of the fallback the dispatch explicitly required reconciling ("a retired value still described as 'falls back to month' is a new contradiction"). Declared here as the dispatch-mandated increment; no packages/plugin-calendar source needed changing (registry side already correct).

Verification (union re-run at e168a0a43, the PR head)

  • pnpm --filter @object-ui/types type-check && pnpm --filter @object-ui/plugin-calendar type-check — green (scripts echoed).
  • pnpm exec vitest run packages/types/ packages/plugin-calendar/ from repo root — Test Files 56 passed (56), Tests 590 passed (590).
  • Ablation (predicted before running): restored the old enum from origin/main (mutation anchored on disk — enum-line grep 0→1), reran the new pin — Tests 3 failed | 3 passed (6), exactly the predicted split (rejection legs red, survivors/passthrough green); trap-restored, restore confirmed by grep (1→0) and clean git status.
  • Rebuilt-.d.ts reverse verification: tsc probe against packages/types/disterror TS2322: Type '"agenda"' is not assignable to type 'CalendarViewMode'; the 'week' control compiles clean.
  • Gates: check:control-bytes ✅, check:spec-symbols ✅, check:doc-types ✅ ("Every documented component type is registered."), check-changeset-presence ✅, check-changeset-no-major ✅, check-changeset-fixed ✅, check:esm-specifiers ✅, @object-ui/types lint 0 errors.
  • Declared narrowing:check:doc-snippets was not concluded locally — its preflight red is the known unbuilt-closure gauge ("The snippet program was NOT run"; it kept naming more unbuilt packages after one bounded build round). The edited docs line is a prose table row, not a snippet; CI's built run is the verdict.

Overlap scan

packages/types is serialised: #5494 (ReferenceRailEntry) is queued behind this card and not dispatched; this PR does not touch that surface. #5494 remains open and is not addressed here.

Generated by Claude Code


Generated by Claude Code

The union declared a value nothing enforced: the registered calendar-view
renderer's `view` input declares enum ['month','week','day'],
resolveAuthoredView resolves 'agenda' to undefined (the component's 'month'
default), and CalendarView renders no agenda view. Zero measured authors of
view: 'agenda' (in-repo, examples, catalog, and the objectstack tree).
Narrowing the accept set is the substance: `view` is a declared key, and
declared keys are validated even under .passthrough(), so view: 'agenda' is
now an invalid_value error on the `view` path where it previously parsed
green. Undeclared keys still pass through. Runtime resolver unchanged.
Value-level residue of objectui#5667's key-level ruling (the renderer is
authoritative; converge the declaration on the measured read set), ADR-0049
enforce-or-remove.
Fixes#5740
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E7snar5mwF7qoXJazqKhys
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3918.4 KB3990.2 KB
Main entry chunk (gzip)152.5 KB350 KB
Entry fileindex-Ds6R0DmO.js
StatusPASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)10.04KB3.72KB
app-shell (runtime-config.js)12.80KB4.47KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)33.99KB8.57KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)503.77KB113.91KB
core (index.js)4.92KB1.97KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)164.55KB45.67KB
fields (index.js)238.40KB59.89KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.95KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.53KB3.38KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.64KB1.50KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)1.93KB0.88KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.65KB18.32KB
plugin-chatbot (index.js)181.41KB43.22KB
plugin-dashboard (index.js)128.41KB32.95KB
plugin-designer (index.js)212.30KB42.80KB
plugin-detail (index.js)242.34KB60.98KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)125.63KB30.64KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)200.79KB54.26KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.80KB27.20KB
plugin-map (index.js)20.06KB6.62KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.49KB11.93KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.61KB20.74KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)44.39KB14.99KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)12.13KB3.65KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.88KB1.85KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)3.40KB1.68KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-samClaude

Copy link
Copy Markdown
CollaboratorAuthor

Build Docs red here is #5668, not this PR — and this time it was a real build, so I read the trace

Stating it once with the evidence, rather than pushing anything at it.

This run was not one of the ~11-second cached greens seen on sibling PRs — it ran 3m43s and genuinely built. That is precisely the case worth checking rather than assuming, so the trace was read:

Error: Module not found: Can't resolve 'fs'
./node_modules/.pnpm/pg-connection-string@2.14.0/…/index.js:88:70
Import traces:
pg-connection-string ← @objectstack/spec@17.1.0 ← @objectstack/formula@17.1.0
← packages/core/dist/evaluator/fieldRules.js ← packages/components/dist/index.js
← apps/site/app/components/InteractiveDemo.tsx
Tasks: 28 successful, 29 total · Failed: @object-ui/site#build

Byte-identical to the signature recorded on #5668, which documents this as red on main across four consecutive push runs.

Why it is not this diff. This PR changes packages/types/src/complex.ts, its zod mirror, one prose table row in content/docs/api/schema-reference.md, a pin test and a changeset. None appears in that chain, and none can change module resolution. Two further readings make that concrete:

  • fieldRules.ts already imported @objectstack/formula before this PR existed — the chain is pre-existing.
  • The trace names statistic.mdx.js and plugin-timeline.mdx.js — different routes than the sibling failure on feat(types,plugin-calendar): converge CalendarViewSchema on the calendar-view renderer's read set #5739 named (plugin-form / plugin-gantt), and neither is schema-reference.md, the only doc file this PR touches. Turbopack simply reports whichever route it reached first; the failure is graph-wide module resolution, not route-specific. If this PR's doc edit were the cause, the trace would name that file.

Not pushing a fix, and not re-running. The remedy is @objectstack/spec's browser reachability — outside this card's declared surface, owned by #5668 under domain:devx. A re-run cannot change a base-branch failure, and this is not a flake.

It does not gate the queue: 30+ PRs have merged to main in this state since #5668 was filed, including all four this lane landed today.

This PR's own gates are read separately and by name; Build Docs is excluded from that reading with the justification above — excluded with cause, not counted as green.

Worth recording for #5668's owner: this is now the second real (uncached) reproduction observed today, and the varying MDX route between runs is evidence the failure is in the shared client graph rather than in any particular doc page.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@os-sam@claude