Skip to content

retire(types): remove the EventHandlersSchema published export (ADR-0049 enforce-or-remove) - #9552

Merged
claude[bot] merged 5 commits into
mainfrom
claude/issue-6910-retire-event-handlers-schema
Sep 15, 2026
Merged

claude[bot] merged 5 commits into
mainfrom
claude/issue-6910-retire-event-handlers-schema

Conversation

@claude

@claude claude Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #6910

Retires the published export EventHandlersSchema (z.record(z.string(), z.function())) from @object-ui/types under ADR-0049 enforce-or-remove, per the maintainer ruling recorded on the card (decision batch #25, reconfirming batch #8 on objectui#6124).

This is a resume. The branch already carried a WIP commit that deleted the export and the barrel line and left a NOTE in place; that commit was deliberately incomplete and red by construction. This PR merges origin/main into the branch (merge, never rebase), then finishes the remaining halves.

What landed

# File Change
1 zod base module export + declaration already gone on the WIP; NOTE corrected twice, see below
2 zod barrel re-export line already gone on the WIP; verified
3 zod-mirror-parity.test.ts the self-contained two-line EXCLUSIONS entry for the removed const, deleted
4 handler-keys-json-refusal-6124.test.ts the MIRROR_FILES docblock sentence the removal falsifies, rewritten
5 .changeset/6910-retire-event-handlers-schema.md one changeset

The expected red, and its resolution

Removing the export turns the stale-entry census in zod-mirror-parity.test.ts red with exactly ['base.zod.ts#EventHandlersSchema'] — that census reads exported consts off disk, so it fires for any route that removes the export. Edit 3 is what clears it. The whole package runs 190 files / 4515 tests, all passing, with type-check green across all three tsc passes.

The deleted row's reason string is shared verbatim with the sibling HTMLAttributesSchema entry, so the deletion was anchored on the key line, not on the reason text; the sibling entry is untouched and still present.

Round 2 — contract review F1 (MAJOR), repaired

The review reproduced 8 of 8 claims and added two checks of its own that strengthen this PR: a set difference over all 489 EXCLUSIONS keys (exactly one key removed, the sibling surviving at the identical address on both refs), and a red-first proof that re-adding the retired row turns the census red naming only that key — so the delete was mandatory, not a test weakened to go green.

It also found that my rewritten NOTE had shipped a born-false census sentence: "every authored events in the corpus is TimelineSchema.events, an unrelated array."

The instrument behind that claim was itself the defect. I had matched only the JSON-quoted "events": spelling, which structurally cannot see a TypeScript object literal, and then generalised the result to "the corpus". Re-measured on this branch over the tracked files under packages/, apps/ and examples/, with a live control that fires and a clean absent-token control at zero, the object-literal form finds the node-level record shape the paragraph warns about — on nodes that are not timelines — plus a larger set of hook and validation string arrays. Of the files declaring a type: 'timeline' node, the only ones carrying an events key are the declaration itself and a refusal probe. TimelineSchema.events is authored zero times. The sentence was wrong in both directions.

This was the defect the rewrite existed to remove, recurring inside its own fix, and it reached the emitted .d.ts. No replacement count is written. The paragraph now states the mechanism, which does not rot — nothing declares the key, nothing reads it, so whatever a document writes there no renderer runs it — points at objectui#9553 for the census, and records that it shipped a frozen census answer once already. The operative instruction is unchanged: .passthrough() ⇒ kept, judged by nothing, run by nothing, do not send an author there.

Deviation from the WIP commit, stated rather than folded in

The WIP NOTE told the reader that handlers are authored as BaseSchema.events. That is false on this tree, and it is the one thing in the inherited work that was not adopted as-is: BaseSchemaCore has 21 members and declares no events; the TypeScript BaseSchema interface declares none either; schema.events and props.events have 0 read sites across packages, apps and examples, against live controls schema.className and schema.visible firing in the same pass; and @objectstack/spec 17.4.0 declares no UI-node events keyed to actions.

Shipping that sentence would have replaced one unauthorable surface with a pointer to a non-existent one, which is the exact hazard this card exists to remove. The NOTE now points at the real JSON face — handlerKeyRefusal() and the node-type spelling PR #6498 established.

Consumer verification

repo result control
objectui (re-taken here) 5 occurrences / 5 files on origin/main, zero composition consumers BaseSchema → 429 files, fires; absent-token → 0
objectstack (re-taken here) 0 BaseSchema fires in the same corpus
cloud 0 — ⚠️ INHERITED, not re-taken live substituted control @object-ui/*, 16 files
hotcrm 0 — ⚠️ INHERITED, not re-taken live substituted control @object-ui/*, 3 files

The cloud and hotcrm legs are carried forward from the published reading on objectstack#15886 and are not presented as readings this seat took; this container holds no access to either repo.

Reverse verification against the rebuilt dist rather than a cache: the built zod barrel exposes 211 named exports, the removed symbol is absent from it, and three sibling controls (HTMLAttributesSchema, BaseSchema, ClassNameStylePropsSchema) all resolve.

Acceptance notes

The changeset's level came from the gate's own verdict, not from a sibling card. check-changeset-presence scored this change @object-ui/types, "Scored minor at most, never major", so the declaration is minor.

On the BREAKING banner (review F2), answered explicitly. The reviewer is right that the distinction I originally drew from objectui#9040 — "that one had a live consumer face, this has none" — is not supported: 9040 also recorded a zero in-repo census and took the banner anyway, and both removals produce an external compile error. I withdraw that reasoning. The banner is nonetheless omitted, for a different and narrower reason: this card's ruling names the banner as a conditional and the condition was not met. The ruling states that a live import anywhere means "the ruling stays retire but the changeset becomes BREAKING and the removal needs ADR-0087's conversion path rather than a plain delete". The four-repo census came back zero, so the plain-delete branch is the one the ruling itself selects. That is a ruled branch, not a house-style judgement, and it is not mine to override; 9040 is a different card under its own ruling. The body still tells a consumer plainly that an external import breaks and gives the FROM/TO, which is what a CHANGELOG reader needs either way.

The fifth occurrence is left alone, and three instruments agree. .changeset/6124-handler-keys-json-refusal.md says "EventHandlersSchema is objectui#6910's card". That is a scope statement about what objectui#6124 did not cover, it stays true after the removal, check-changeset-overwrite exists precisely to report editing a changeset you do not own, and AGENTS.md #11 forbids re-addressing a published record. Not touched.

Dist residue (review F3), corrected count. The removed symbol survives in the built output 3 times: 1 in dist/zod/base.zod.d.ts and 2 in .js files (zod/base.zod.js, zod/index.zod.js) — all of them the NOTE's own prose carried through as a comment. No declaration and no export: a grep for either in dist returns 0.

Out-of-scope finding, filed rather than fixed here — AGENTS.md's abridged JSON-protocol sketch publishes an optional events member typed as a record of event-name string to ActionSchema array as a BaseSchema member, and its action-system commandment authors one, while no schema declares the key and nothing reads it. Because BaseSchemaCore is .passthrough(), a node written from that sketch is kept by the parser, judged by nothing and run by nothing — a silent discard, and the carrier is the file agents read first. Filed as objectui#9553, whose own census has been corrected for the same instrument error described above. AGENTS.md is a governed surface and is not touched by this PR.

Gate readings. Green here: the changeset family (presence, no-major, overwrite, claims), control-bytes, new-line-citations, handler-key-reads, spec-symbols, test-path-roots, unreferenced-sources, the package's type-check, and the package suite. check:readme-exports is NOT MEASURED locally — it exits 1 on an unbuilt tree and prints "the population COLLAPSED -- this run proves nothing", a prerequisite failure and not a finding; it needs a full repo build and belongs to CI. It cannot be moved by this diff in any case: 0 READMEs name the removed symbol, against control BaseSchema firing in 13 of 54 tracked READMEs. check-governed-queue-guard is CI-only; its surface list was read directly instead, and none of these paths is governed.

Clause-②: yes — a published export is removed. The needs:contract-review carrier is the PM's to hang; no label was touched by this seat, on the card or here.

Implemented-by: claude/issue-6910-retire-event-handlers-schema


Generated by Claude Code

…erately untouched

⛔ NOT a finished change. The public export `EventHandlersSchema`
(`z.record(z.string(), z.function())`) and its barrel line are removed and the
knowledge is preserved as a NOTE at the declaration site, per the maintainer
ruling on objectui#6124 (decision batch #8, reconfirmed batch #25) recorded on
objectui#6910.

The third half of that ruling — deleting the parity-ledger row
`'base.zod.ts#EventHandlersSchema'` in
`packages/types/src/__tests__/zod-mirror-parity.test.ts` — is NOT in this commit.
That file is held by the open PR #8763, and this seat's dispatch forbids editing
it. So this tree is RED BY CONSTRUCTION: `zod mirror parity — the population is
closed > no map entry names a const that no longer exists` fails with
`['base.zod.ts#EventHandlersSchema']`. Measured, not predicted.

No PR is opened from this commit. It exists so the NOTE and the measurements
survive the hand-off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012W3vMLTFY9SPr2LyxhSeYi
…e halves

Completes the retirement the WIP commit on this branch left deliberately
incomplete. The public export and its barrel line were already gone; this
commit removes the parity-ledger row the removal reddens, repairs the one
docblock the removal falsifies, and declares the change.

- zod-mirror-parity.test.ts: delete the self-contained two-line EXCLUSIONS
  entry for the removed const. Its stale-entry census reads exported consts
  off disk, so the row went red the moment the export left; the sibling
  HTMLAttributesSchema entry shares the same reason string and is untouched.
- handler-keys-json-refusal-6124.test.ts: the docblock over MIRROR_FILES said
  base.zod.ts "holds only EventHandlersSchema ... and no named key", which the
  removal makes false. Rewritten to state why base.zod.ts is not one of the
  nine mirror files; the block is kept, since it is what explains the census
  population.
- base.zod.ts: correct the NOTE. It claimed handlers are authored as
  BaseSchema.events, an event-name string keying ActionSchema[]. Checked
  against the tree rather than inherited: BaseSchemaCore declares no events
  member, nothing reads schema.events, and every authored events in the corpus
  is TimelineSchema.events, an unrelated array. The NOTE now points at the
  real JSON face -- handlerKeyRefusal() and the node-type spelling -- and
  records the stale sketch as a trap rather than repeating it.
- One changeset, scored minor by the presence gate's own verdict, with no
  BREAKING banner: the four-repo consumer census is zero.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3062.9 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-DFFWqHgz.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 544.93KB 130.50KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.20KB 62.88KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.99KB 14.24KB
plugin-charts (index.js) 71.33KB 19.90KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 252.48KB 65.61KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.83KB 57.97KB
plugin-kanban (index.js) 46.63KB 14.53KB
plugin-list (index.js) 112.67KB 27.68KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 84.89KB 20.96KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 99.04KB 32.62KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 14.82KB 4.99KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.04KB 5.36KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

Contract review F1 (MAJOR). The NOTE's warning paragraph asserted that "every
authored events in the corpus is TimelineSchema.events, an unrelated array".
That was wrong in both directions on the day it was written, and the whole
comment block is emitted into the published .d.ts, so it shipped.

The instrument behind the claim was the defect: it matched only the
JSON-quoted "events": spelling, which cannot see a TypeScript object literal.
Re-measured here over the tracked files under packages/, apps/ and examples/
with a control that fires, the object-literal form finds the node-level record
shape the paragraph warns about, plus hook and validation string arrays; and
of the files declaring a timeline node, the only ones carrying an events key
are the declaration itself and a refusal probe. TimelineSchema.events is
authored zero times.

No replacement count is written. The paragraph now states the mechanism, which
does not rot -- nothing declares the key and nothing reads it, so whatever a
document writes there, no renderer runs it -- and points at the card that
carries the census. A census answer frozen into a comment is what AGENTS.md
commandment #9 forbids, and this note had reproduced that defect inside the
very fix performed to record it; the paragraph now says so.

The operative instruction is unchanged: BaseSchemaCore is .passthrough(), such
a node is kept, judged by nothing and run by nothing, do not send an author
there.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3063.0 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-BVsg3f-g.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 544.93KB 130.50KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.20KB 62.88KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.99KB 14.24KB
plugin-charts (index.js) 71.33KB 19.90KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 252.48KB 65.61KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.83KB 57.97KB
plugin-kanban (index.js) 46.63KB 14.53KB
plugin-list (index.js) 112.67KB 27.68KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 84.89KB 20.96KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 99.04KB 32.62KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 14.82KB 4.99KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.04KB 5.36KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Test (shard 1/4) is red, and it is not this PR's — standing down, with the reason

domain:spec @ objectui execution seat, session session_01L5xpA5q533BgTTNADibEFt,
reading 2026-09-15T03:40Z. ⛔ This PR is not being widened to carry a fix for shared test
infrastructure.

The failing check, and what actually failed

Test (shard 1/4) at head 53df540f0847ca38db6b27586bda9238644840bc, job 104240335341,
failure after 944 s. Shards 2/4, 3/4 and 4/4 are success at the same head
(826 s / 1020 s / 992 s). Census: 36 runs, 32 success, 3 skipped, exactly 1 failure.

FAIL  scripts/__tests__/check-i18n-dead-keys.test.ts > … > NEGATIVE: keys nothing reads still
      have no textual footprint at all
Error: Command failed: grep -rFn -I --exclude-dir node_modules … -- /home/runner/work/objectui/objectui
grep: /home/runner/work/objectui/objectui/.vite-oracle-9408-XeSa8U: No such file or directory
Serialized Error: { status: 2, … }

Test Files 1 failed | 784 passed | 1 skipped · Tests 1 failed | 10750 passed | 2 skipped.

Why it is not this PR's — mechanism, not assertion

Two test files race over a scratch directory one of them creates inside the repo root. Both ends
re-verified on origin/main, ⛔ not inherited:

  • Producer: scripts/__tests__/vite-objectstack-spec-dist.test.ts calls
    fs.mkdtempSync(path.join(repoRoot, '.vite-oracle-9408-')) — and vite-oracle occurs exactly
    once
    in the whole tree, so that is the only producer.
  • Consumer: scripts/check-i18n-dead-keys.mjs's textFootprint() sweeps the repo root with
    grep -rFn -I. The scratch directory disappears mid-walk, grep exits 2, and the script's
    catch re-throws anything that is not status 1 — deliberately, with a comment saying so.

⇒ the failure needs a concurrent scheduling of two files in scripts/__tests__/. This PR's diff
is 9 insertions / 6 deletions of comment prose in packages/types/src/zod/base.zod.ts, plus an
origin/main merge.
It cannot reach either end of that race.

Already filed, and this is its third instance — ⛔ no fix exists to port

objectui#9468 carries this defect with both ends located. My occurrence is recorded there as
a third instance:
the same failure hit PR #9366's head 87cab756a9 on 2026-09-14, and that card's body concluded
"one occurrence, did not recur" — which this run falsifies, 21 hours later on an unrelated PR.

The card is open, bare and unassigned; there is no fix to port into this PR, and per this lane's
rules a ported fix is the only thing that would ride here. ⭐ Nor should one be improvised: #9468's
own warning is that widening the catch would trade a loud race for a silent one — an
under-counted sweep that the gate would pass. The repair belongs at the producer or in the sweep's
exclusion set, on that card, with a review.

What happens next on this PR

One re-run of the failed job — the single re-run this lane allows, spent here to confirm the race
rather than to wish the failure away. If it comes back green, this PR lands on the gates already
taken (verdict PASS at this head, carriers agreeing, and the rest of the census green). If it fails
again on the same assertion, that is a second reading of the same race on one commit and I will say
so rather than re-running further.

⛔ Nothing about the contract review changes: the verdict stands at PASS for
53df540f0847ca38db6b27586bda9238644840bc.


Generated by Claude Code

@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

needs:contract-review discharged — the record, then the removal, then the gate

Seat: domain:spec @ objectui, os-sam, session session_01L5xpA5q533BgTTNADibEFt, read at 2026-09-15T04:02Z.

The review of record

field value
verdict PASS — comment 5674344635, 2026-09-15T03:35:56Z
declared head 53df540f0847ca38db6b27586bda9238644840bc
pulls/9552.head.sha now 53df540f0847ca38db6b27586bda9238644840bc
comparison full 40-character string equality, both operands length 40 — ⛔ not a prefix and not a short sha
authorship pair Implemented-by: claude/issue-6910-retire-event-handlers-schema · Reviewed-by: session_01L5xpA5q533BgTTNADibEFt, each token immediately after its colon

The round-1 verdict returned FAIL on F1 (MAJOR) — a born-false census sentence in the rewritten NOTE, produced by a JSON-quoted matcher that structurally cannot see a TypeScript object literal. The repair removed the count rather than replacing it, because the defect was the shape of the claim, not its value. The targeted re-check confirmed the repaired paragraph carries no census, that the reviewed head ee48fcee7b is still an ancestor of 53df540f08 (nothing rebased, amended or force-pushed), and that F1's text is gone from source and from the rebuilt dist.

The red that was not this PR's, and its resolution

Test (shard 1/4) failed on a repo-root scratch-directory race, which is the already-filed objectui#9468 and was recorded on that card as its third instance — falsifying that card's own "did not recur". I spent the one re-run this lane allows, said so before spending it, and committed to reporting a second failure as a second reading of the same race rather than re-running further. It came back completed: success at 2026-09-15T04:02:09Z, so that commitment did not have to be exercised.

Gates at this head

  • ① declared head == pulls/9552.head.sha, compared as full strings. MET.
  • ③ total_count 36 == 36 returned; {success: 33, skipped: 3}; 0 not-green, 0 still running; legacy combined status success (1 context); mergeable_state: clean. MET. ⚠️ This is the draft check set — a check that only starts on undraft would be a 37th, so ③ is re-taken after the flip and before the queue, not carried forward from here.
  • ② is taken after this removal, deliberately. See below.

⭐ Why gate ② is read after the carrier comes off, and not before

On PR #9548 earlier this shift I removed this same carrier while the verdict still carried a half-written authorship pair, opening a five-minute carrier-free window over a verdict the gate would have rejected. The root cause is not carelessness about ordering — it is that the ordering the obvious reading suggests cannot work: while needs:contract-review hangs, check-clause2-carriers cannot read the PR thread, so every row that reads the verdict's text is silent, and a blind run and a genuine pass emit the same bytes.

One line, so it survives out of context: a checker whose inputs are gated by the carrier it is deciding to remove cannot produce the reading that authorises the removal.

So the sequence is: this record → the targeted DELETE on PR #9552 and on card objectui#6910, each read back as a JSON set difference → then --pair 9552 as the landing reading of ②. If ② comes back non-zero after the removal, the carrier goes back on in the same shape and this PR does not move.


Generated by Claude Code

@claude
claude Bot marked this pull request as ready for review September 15, 2026 04:03
@claude
claude Bot added this pull request to the merge queue Sep 15, 2026
@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Enqueued — three of three at 53df540f08, in the order that makes ② readable

Read and written 2026-09-15T04:02–04:04Z by domain:spec @ objectui, os-sam, session session_01L5xpA5q533BgTTNADibEFt.

# gate reading at
① declared head == pulls/9552.head.sha 53df540f0847ca38db6b27586bda9238644840bc both sides, full 40-character string equality 04:02:35Z
② PM_SWEEP_REPO=objectstack-ai/objectui node scripts/pm/check-clause2-carriers.mjs --pair 9552 exit 0 — declaration readable in the fixed spelling, both carriers agree, and C6-RECORD names comment 5674344635 as the review of record on this head 04:03:33Z, after the carrier came off
③ check census, pre-flip 36/36, {success: 33, skipped: 3}, 0 not-green, 0 running, legacy combined success, mergeable_state: clean 04:02:35Z
③ check census, re-taken post-flip 37/37, {success: 34, skipped: 3}, 0 not-green, 0 running, legacy combined success, mergeable_state: clean, head unmoved 04:04:27Z

⭐ The 37th check is the reason ③ is taken twice. Governed Surface Queue Guard ran once on the draft (03:22:57 → 03:23:11Z) and again on the undraft (04:03:54 → 04:04:05Z), and only the second reading is about the PR that is being enqueued. ⚠️ That second run took 11 s; the band this lane has been quoting was 12–28 s, so it is now 11–28 s over the readings taken — a range, ⛔ not a sample.

Sequence, with its timestamps, since the ordering is the point: discharge record 5674547457 → targeted DELETE of needs:contract-review on this PR and on card objectui#6910, each read back as a JSON set difference ({needs:contract-review, package: types, tests} → {package: types, tests}; {domain:spec, needs:contract-review, pm:dispatched, priority:p3} → {domain:spec, pm:dispatched, priority:p3}; nothing unexpectedly added or removed on either) → gate ② → ready_for_review 04:03:49Z → guard → gate ③ again → auto_merge {"merge_method":"SQUASH"} 04:04:39Z.

added_to_merge_queue is on the timeline at 04:04:40Z. ⚠️ auto_merge reads back null once a PR is queued, so the timeline event is the evidence and the field is not. Queue transit has been 18.5–20.5 min over ten readings this shift, the most recent being PR #9551 at 20 min 09 s — so a merge is expected around 04:23–04:25Z, and that is a range this seat keeps re-measuring rather than a promise.


Generated by Claude Code

Merged via the queue into main with commit 40f34b4 Sep 15, 2026
47 of 48 checks passed
@claude
claude Bot deleted the claude/issue-6910-retire-event-handlers-schema branch September 15, 2026 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant