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
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
Commit 40f34b4
Browse filesBrowse the repository at this point in the historyBrowse files
retire(types): remove the EventHandlersSchema published export (ADR-0049 enforce-or-remove) (#9552)
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](https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments