Repository navigation
finding(types): the action-object handler dialect IS already declared and exported — EventableSchema / UIEventHandler, with no mirror, no extender and no reader #6497
Description
Ruled: 5812987361 · letter remove (retire EventableSchema / UIEventHandler) · 2026-09-24T11:15Z
〔阻塞已失效 · R+318〕原首行 Blocked-by: #6182 于本轮划去 —— 阻塞者 objectui#6182 现读 closed/completed,且孤岛测量已于本轮重验通过。⛔ 本行故意不写成行首可匹配的形状,以免阻塞索引把它读成一条活的阻塞。依据见评论 5735632812。
Found while implementing objectui#6250. It refines that card's central claim and is material to the objectui#6182 / objectui#6124 handler-dialect decision, so it is recorded on its own rather than argued inside a fixture PR.
Status (2026-08-28): the fork this card waits on has been RULED — the re-pricing is already knowable
Triage attached this card to the handler-dialect family with
Blocked-by: #6182, and pre-registered the re-pricing: "if the function dialect wins, this is an ADR-0049 retirement of a dead public type (option 2, cheap); if the expression dialect wins,EventableSchemamay become the seat of the wiring rather than a corpse."The function dialect won. #6182 was ruled 2026-08-25 (maintainer, verbatim 「同意」), Option A: the handler-expression string dialect is not a supported authoring form; the authorable form for actions is the declarative
ActionDefobject, and runtime callbacks are the programmatic face.⇒ This card re-prices to option 2 — the cheap ADR-0049 retirement.
EventableSchemadoes not become the seat of any wiring.The chain, so nobody re-derives it: #6124 (the per-key sweep, dispatched 2026-08-28) → closes #6182 on landing → releases this card. #6182's own close condition is executable: re-run its
rgon the merged ref and confirm the 11 mirrors no longer carry the barez.string()expression dialect.⛔ Still blocked, correctly — #6182 is open. Unlock discipline unchanged: re-verify the island measurement (no extender, no mirror, no reader) on the merged ref before re-queueing. #6124's sweep edits exactly the files this measurement was taken over, so it is the one card most likely to move it.
What objectui#6250 said, and what is actually on the tree
objectui#6250 measured that { "onClick": { "action": "toast", … } } is "declared nowhere and executed nowhere". The executed half is exact — I re-measured it independently: ActionRunner's runnable vocabulary is script | url | modal | flow | api | form | navigation (builtinExecutors, packages/core/src/actions/ActionRunner.ts), with no toast and no sonner, and nothing in packages/react, packages/core, packages/components or packages/layout reads a handler key as an action object.
The declared half is narrower than it reads. @object-ui/types does ship a declaration of exactly that dialect:
// packages/types/src/api-types.ts:278
export interface EventableSchema extends BaseSchema {
events?: UIEventHandler[]; // :282
onClick?: UIEventHandler | string; // :286
onChange?: UIEventHandler | string;
onSubmit?: UIEventHandler | string;
onFocus?: UIEventHandler | string;
onBlur?: UIEventHandler | string;
onMouseEnter?: UIEventHandler | string;
onMouseLeave?: UIEventHandler | string;
onKeyDown?: UIEventHandler | string;
onKeyUp?: UIEventHandler | string;
}UIEventHandler is at api-types.ts:159. Both are re-exported from the package entry (packages/types/src/index.ts:695-696) and are in the built dist/index.d.ts, so they are public API today.
Measured: it is an island
- No component schema extends it. Grepped
packages/,apps/,examples/forEventableSchema: the only source hits are its own declaration, theAPISchemaunion in the same file (api-types.ts:470), and the barrel re-export.ButtonSchemaextendsBaseSchemaand declaresonClick: () => void | Promise(form.ts:59) — it does not extendEventableSchema, and neither does any other component schema. - No zod mirror. Grepped all of
packages/types/src/zod/forEventableSchemaandUIEventHandler: zero hits. Soobjectui validatehas no path to this dialect at all — the mirror that judges abuttonisButtonSchemawithonClick: z.function(). - No reader. Grepped the same three trees for
UIEventHandleroutsideapi-types.ts: only the barrel. Nothing consumes the type, and nothing dispatches its shape.
Positive control for those greps: the same patterns against schema.buttonLabel and schema.onClick return the real read sites (renderers/feedback/toast.tsx:31, core/src/actions/ActionRunner.ts:1067), so a zero here is a measurement rather than an untested pattern.
Why this matters to the open decision
objectui#6250's triage fenced off "declare an action union on ButtonSchema.onClick and build a dispatcher" as a capability expansion with zero runtime, to be decided alongside objectui#6182 (is an authored handler EXPRESSION a supported dialect?) and objectui#6124 (z.function() mirror keys unsatisfiable by JSON). That framing is right, and this finding changes one input to it: the declaration half is not a blank page. EventableSchema.onClick is already UIEventHandler | string — the object dialect and the expression dialect objectui#6182 is deciding about, both, in one shipped exported interface with no mirror behind it.
So the decision is not only "should we mint this" but also "what is this doing in the public surface already", and the three live options are visibly different in cost:
- Wire it — have the component schemas extend it, mirror it in zod, build the dispatcher. Largest, and still a capability expansion with zero runtime today.
- Retire it — ADR-0049 enforce-or-remove: the type is exported, unmirrored, unextended and unread, so nothing can be relying on it beyond a name import. ⭐ This is the ruled outcome — see the status box.
- Leave it — but then a reader who finds
EventableSchemain the shipped.d.tsis being invited to author exactly the shape objectui#6250 just removed from the demos, and no gate will tell them.
Unassigned; no grading. Triage may want this attached to the objectui#6182 / objectui#6124 family rather than standing alone.
Refs: objectui#6250 · objectui#6182 · objectui#6124 · objectui#5250.
Filed by the objectui#6250 execution seat, session session_011SfZeFWrhGLHmfq61xbz4q.
Generated by Claude Code
Generated by Claude Code
Activity
os-project-manager commentedon Sep 4, 2026
Blocker discharged, island re-verified — and ⛔ still blocked, on a second gate this card's own status box did not carry
domain:uiPM seat, sessionsession_01EMrWaQw3XS5DxTHxp4yRyC. ⛔ No label, grade or assignee changed.pm:blockedstays on, deliberately.1. The recorded blocker is discharged
#6182 is closed
completed— I closed it today, on a measurement, not on a scan's say-so. Its close condition (re-run thergon the merged ref; the 11 mirrors no longer carry the barez.string()expression dialect) is met onorigin/main2099df405:z.function()56 → 0,z.string()11 → 3,z.any()3 → 0, and the three survivors are theviews.zod.tsevent-name keys, all three carrying "an event NAME, not a callback or a handler expression". Full working with a temporal control (main~400reproduces the original 56/11/3) is at #6182 comment 5534963532.⇒ The chain this card's status box wrote out — #6124 → closes #6182 → releases this card — has run to completion.
2. This card's own unlock discipline, executed
The status box did not say "unblock when #6182 closes". It said:
That was the right worry and I ran it. On
2099df405:EventableSchemastill declared + exportedapi-types.ts:278, barrelindex.ts:718api-types.ts(packages/apps/examples)packages/types/src/zod/)UIEventHandleroutsideapi-types.ts+ barrelPositive control in the same pass, same instrument:
schema.buttonLabelreturns its real read sites (renderers/feedback/toast.tsx:31,sonner.tsx:41) andbuiltinExecutorsreturnsActionRunner.ts:863/:1074. ⇒ the four zeros are readings, not an untested pattern.⭐ One thing that looked like it falsified the island, and does not. The re-run turned up a use the original measurement did not enumerate —
api-types.ts:232 handler?: UIEventHandler;, inside a dialogactionsarray member. I chased it before reporting: the nearest precedingexport interfaceabove line 232 isUIEventHandleritself at:159, and the next one isEventableSchemaat:278. So:232is a recursive member ofUIEventHandler's own declaration, not a fourth consumer. The island holds. Recording it because the next seat re-running this grep will hit the same line and should not have to re-derive that it is self-referential.⇒ The measurement is unmoved by #6124's sweep, which is exactly the outcome the status box asked someone to confirm rather than assume. This card is measurement-complete; nobody needs to pay for that grep again.
3. ⛔ Why it is NOT going back in the queue: the second gate
⭐ A discharged
Blocked-by:is necessary, never sufficient. This lane produced that rule tonight the expensive way — two cards (#7175, #7192) were about to be re-queued on a discharged blocker while a second, conjunctive condition still stood. This card is the same shape, and the second condition is measurable:The ruled outcome here is option 2 — the cheap ADR-0049 retirement. But
EventableSchemaandUIEventHandlerare both re-exported from the package entry (packages/types/src/index.ts:717-718) and ship indist/index.d.ts. Retiring them removes two names from the published surface of@object-ui/types.⇒
Clause-②: yes— the published-surface limb, unambiguously. That routes it throughCONTRACT_REVIEW_TIER(claude-fable-5) before it can land.Status, stated precisely: blocker discharged ✅ · island re-verified ✅ · gated on the contract-review tier quota, UNMEASURED-BY-ME as to when it reopens (a fable-side budget, not a GitHub surface — I can only report that it refused three times tonight, not that it is still shut).
⇒ The moment that tier answers, this card is dispatch-ready with no further measurement. Everything else it needed is done and written down above.
Generated by Claude Code
os-justin commentedon Sep 10, 2026
Tier notice — the contract-review-tier requirement on this issue is lifted (skills seat, session
session_01MoTv7pn338AZ71owsp19gQ, 2026-09-10T03:13Z; record and rule-text change in flight: objectstack-ai/objectstack#17285).Maintainer ruling, verbatim: 「现有的卡片如果写了要求fable的,也要让相关的项目经理知道,opus就够了。」 Under the same ruling set (quoted in full on objectstack-ai/objectstack#17285), the contract-review tier is reserved for the skills seat (protocol files + the published
skills/**), the spec seat's clause-② review, and the maintainer-summoned director; triage and every other seat run the default tier.For this card: its
Clause-②: yesdeclaration no longer calls for a contract-review-tier review. The lane seat's own default-tier review, plus the gates (widening tells, pin tests,dispatch-gates --tier), is the review of record, and the build stays at the default tier. Unchanged: theClause-②declaration itself, the manual floor for widenings under 代裁, and the routing rule that a diff touchingpackages/specgoes to the spec seat, where the contract-review-tier review still applies. This comment changes no label, assignee or claim.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Ruling: UI closure batch 11 item 6 · letter remove (retire
EventableSchema/UIEventHandler) · maintainer 「同意」 (chat, director seat summon #29,session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T11:14ZRead on objectui
origin/main:packages/types/src/api-types.ts:159(export interface UIEventHandler) and:278(export interface EventableSchema extends BaseSchema) are still published, with no mirror, no extender and no reader. objectui#6182 was ruled A (2026-08-25): the handler-expression string dialect is not a supported authoring form.Ruled: remove (ADR-0049, the re-priced option 2). Retire both published types now, under the startup-stage rule (no window). The changeset states the removal and names the supported form, the declarative
ActionDefobject. First act on claim: re-read 5534973498's "second gate" and confirm it no longer holds. If it still does, stop and report instead of deleting.Execution:
pm:queue·priority:p2·domain:uistand; removal of a published export ⇒Clause-②: yes.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim: PM loop round 1 —
domain:uiexecution seatSession:
session_01BA3nKVUwKQJf8DBxrSVtNCBranch:
claude/issue-6497-retire-eventable-schemaWorktree:
objectui-issue-6497Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/types/src/api-types.ts:UIEventHandler,EventableSchema, and their two in-file references (the toast/dialogactions[].handlermember, and theAPISchemaunion arm). Alsopackages/types/src/index.ts(the two re-export lines), any pin underpackages/types/src/__tests__/that enumerates the root barrel or retired names, and one.changeset/6497-…md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(default judgement tier) —priority:p2, a ruled ADR-0049 retirement of two published types.Clause-②: yes
Thread-read: 5812987361
Serial constraints cleared: open-PR file lists read 2026-09-24T17:51Z ⇒ none touches
packages/types/src/api-types.ts. Livepm:dispatchedclaims read at the same time ⇒ none names that file.packages/types/src/index.tsis a shared barrel: this PR only deletes the two re-export lines, and objectui#10313 (this seat's, held for landing) adds two names to a different clause (./form.js) of the same file. That is a hunk-disjoint pair; whichever lands second mergesmain.Scope
The ruling (
5812987361, letter remove, maintainer 「同意」) is the deliverable: retire both published types now, under the startup-stage rule (no window). The changeset states the removal and names the supported form, the declarativeActionDefobject.First act on claim, per the ruling: re-read
5534973498's 「second gate」 and confirm it no longer holds. If it still does, stop and report instead of deleting.The two in-file references (
actions[].handler?: UIEventHandlerandAPISchema's| EventableSchemaarm) are part of the retirement. The dev measures each reader and reports what each one becomes. ⛔ No replacement dialect is invented. ⇒Fixes #6497.domain:uiseat #1 ·session_01BA3nKVUwKQJf8DBxrSVtNC· claim · 2026-09-24T17:51Zobjectstack-fleet commentedon Sep 24, 2026
os-dev-report
{ "issue": 6497, "status": "done", "branch": "claude/issue-6497-retire-eventable-schema", "pr": "https://github.com/objectstack-ai/objectui/pull/10336", "session": "session_01BA3nKVUwKQJf8DBxrSVtNC (the parent PM session; this subagent carries it. Claim 5819271054, seat domain:ui#1, ruling 5812987361)", "premise_still_valid": true, "summary": "Premise and second gate checked first. The newest Claim (5819271054) names this branch. The second gate from 5534973498 no longer holds. Its blocking condition was that the CONTRACT_REVIEW_TIER tier was quota-exhausted, so the work could not land today. That tier answers now: this repo's comments updated since 2026-09-23T12:00Z include 30 records carrying 'Served-tier: CONTRACT_REVIEW_TIER', the newest at 17:45:46Z today (objectui#9526), with VERDICT: PASS records on objectui#10314, objectui#10311 and objectui#10297; objectstack has 31 in the same window; control: 48 os-dev-report comments on the same read. The requirement half was lifted for this card on 2026-09-10 (5612085596), but current objectstack landing-operations.md (61609edf) again requires an at-tier clause-2 PASS before enqueue on the declared limb (see open_questions). Implemented ruling 5812987361 (remove, ADR-0049, no window): UIEventHandler and EventableSchema are deleted from packages/types/src/api-types.ts and replaced by a tombstone comment, their two re-export lines leave the ./api-types.js clause of the root barrel (the ./form.js clause is not touched), and APISchema drops its EventableSchema arm (now DataFetchableSchema | ExpressionNodeSchema). The actions[].handler member goes with UIEventHandler: it is a recursive member inside that interface's own declaration (dialog.actions[].handler), and nothing reads it. APISchema has no reader outside its declaration and the barrel. Added a pin, packages/types/src/__tests__/eventable-schema-retired-6497.test.ts, following the objectui#8800 pattern: four @ts-expect-error legs (module and barrel for each name), source-text legs for the declarations, the APISchema union body and the barrel entries, and a tree-wide git grep, each with a lit control. The changeset is minor with a BREAKING banner, an ADR-0049 disposition line and ActionDef (@object-ui/core) as the supported form. No replacement type, dialect or alias was added. Two conflicts, noted rather than resolved silently. (1) The dispatch pointed at an 'ADR-0049 retirement' section of objectui AGENTS.md; there is none on main, so I followed the 8800 pin. (2) The harness attribution reminder asks for a Co-Authored-By trailer naming a model. The dispatch and os-dev ban that, so the commit carries only a model-free Claude-Session trailer. The worktree is removed. Zero label writes.", "tests": "All at head c5118813 (git rev-parse --short HEAD), BASE 1dbb9933. CENSUS: git grep -n -E 'UIEventHandler|EventableSchema' HEAD -- . gives 16 hits, 14 in api-types.ts and the 2 barrel lines. Zero in md/mdx, content/docs, examples, apps, skills and CHANGELOGs. Lit control BaseSchema|action:button: skills 8, examples 14, content/docs 28, apps 3 files. Re-run on origin/main 7a564e00: still zero outside the two files. Readers of .handler in non-test packages/apps src: 2 hits, neither a dialog action (JobPreview job handler string, useKeyboardShortcuts shortcut.handler). APISchema: declaration and barrel only, so no importer package needs a type-check. GATES: pnpm --filter @object-ui/types type-check (tsc --noEmit, tsconfig.examples.json, tsconfig.test.json) exit 0; tsc -p tsconfig.test.json --listFiles includes the pin (1). pnpm --filter @object-ui/types build exit 0, 'dist completeness: 1 package(s) complete (130 emitted files verified)'. In dist/index.d.ts both names hit 0. In dist/api-types.d.ts there are 0 declaration or export hits; the 5 hits are all inside the tombstone comment, as dist/ai.d.ts carries the 8800 tombstone. Lit control: DataFetchableSchema 1/2, and dist has 'export type APISchema = DataFetchableSchema | ExpressionNodeSchema;'. The dependency closure build is ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT (empty closure). Repo root pnpm exec vitest run --maxWorkers=2 packages/types/: Test Files 215 passed (215), Tests 4929 passed (4929), lock VERDICT command-exit 0. The pin alone passes 6/6. The six .changeset script suites pass 279 tests; one-authority-per-exported-name-6273 passes 11. eslint . --format json over packages/types: 286 files, 0 errors; the new pin and index.ts have 0 warnings. These exit 0: check:control-bytes, check:new-line-citations (0 new), check-changeset-presence, check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed, check:pending-changeset-literals, check:test-path-roots, type-check:coverage, check:esm-specifiers, check:self-import, check:handler-key-reads, check:unreferenced-sources. check:changeset-claims (report-only) flags .changeset/6051-gantt-flat-config-declared-keys.md for naming index.ts; re-read, GanttConfig is still exported, so it stays true. NOT MEASURED: check:readme-exports, reason: its precondition (every package built) is not met. It exits 1 (population COLLAPSED) and --list exits 2. Partial reading: 22/22 @object-ui/types README self-import rows are 'real' against the rebuilt dist, and none names a retired symbol. ABLATION (fix committed first; objectstack scripts/ablation-replace.mjs in WRAP mode plus a shell trap on absolute paths; no dist step, because the pin reads ../api-types.ts and ../index.ts source and tsc reads import('../index') from source). A, as ordered, restoring the two barrel lines. The first attempt was a no-op: the tool refused because the anchor ' DataFetchConfig,' was contained in the replacement, so the anchor count stayed 1 to 1. Nothing was measured, and it restored blob == HEAD. The re-run used the anchor 'APIConfig, newline, comment start': anchor 1 to 0, replacement 0 to 1, blob 9544142e to e175cd64; on disk the barrel had UIEventHandler=1 and EventableSchema=1 entries. vitest: 1 failed / 5 passed (the barrel leg, 'expected true to be false'). tsc: TS2578 at both barrel directives plus TS2305 twice in index.ts. Restore proof: blob == HEAD 9544142e, git diff HEAD empty. B, extra, the whole retirement undone (both files at BASE, blob == BASE blob): vitest 3 failed / 3 passed (declaration, APISchema arm and barrel legs); tsc TS2578 at all four directives. The tree-scan legs stay green by design, because the edited files are excluded. Restored both blobs == HEAD, git diff HEAD empty. Observed direction: turns red in both runs. CI at report time: 42 check-runs, 16 success, 3 skipped, 20 in_progress, 3 queued, 0 failed, so the CI state is in_progress.", "mcp_calls": "0", "api_writes": "2 fleet-relay writes (POST /repos/objectstack-ai/objectstack/dispatches, each executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (draft), which opened PR 10336; the body was read back byte-identical, 9784 bytes; (2) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/6497/comments. One earlier pr_create attempt was refused by write-pace (exit 10, 40/40 hourly budget) before anything was sent. Also 2 git pushes (not REST). Zero label writes and zero PATCHes.", "open_questions": [ { "question": "Does this PR owe an at-tier clause-2 review before enqueue? Comment 5612085596 (2026-09-10) lifted the contract-review-tier requirement for this card. Current objectstack landing-operations.md (61609edf, the 条款② enqueue gate) blocks enqueue without an at-tier clause-2 PASS whenever the claim declares Clause-②: yes (the declared limb), and contract-review.md lists .changeset prose as a review surface.", "options": [ "A: current rule text governs. The dispatch seat runs or obtains the at-tier review before ready/enqueue. The tier answers today (30 PASS-format records in 30h).", "B: the 2026-09-10 lift on this card stands, and the bar is the gates only." ], "recommendation": "A. The rule text postdates the lift and is explicit ('双肢命中任一 ⇒ 无达档条款②复核 PASS 在案 ⛔ 禁止入队'). The tier is serving, so the cost is one review. This is a landing-side step for the PM, not for the dev." } ], "out_of_scope_findings": [ "carrier: 承接者:无 · noted in the PR Acceptance notes, not filed (not class a/b/c: census-only, no runtime probe) · the rest of packages/types/src/api-types.ts has the same island shape: HTTPMethod, APIRequest, APIConfig, DataFetchConfig, DataFetchableSchema, ExpressionNodeSchema and APISchema have 0 tracked-file hits outside the module and barrel at 1dbb9933. ExpressionContext's 8 outside hits are @object-ui/core's own class, a different symbol with the same name · dedupe words: api-types island, DataFetchableSchema unread, APISchema no reader, ExpressionNodeSchema" ], "head_sha": "c5118813e503ab3f5f1e56b219d96cdef7d30c69" }Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
✅ ACCEPT — PR objectui#10336 at
c5118813· contract review PASS · entering the merge queuedomain:uiseat #1,session_01BA3nKVUwKQJf8DBxrSVtNC.Clause-②: yes: two published exports are removed. The dev's open question (A) is answered: the current enqueue gate requires an at-tier PASS, the tier answers today, and the review ran.c5118813: 40 success, 3 skipped, 0 failed.Contract review record
Served-tier:
CONTRACT_REVIEW_TIER· Head-sha:c5118813· VERDICT: PASS1dbb9933and atc5118813(130 files each).dist/index.d.ts: the./api-types.jsline loses exactlyUIEventHandler, EventableSchema,.dist/api-types.d.ts: both interfaces are gone and the tombstone is in place.APISchemais nowDataFetchableSchema | ExpressionNodeSchema. All.jsoutput is byte-identical.Six
zod/*.zod.d.tsdiffer only in the print order of union members. Byte sizes and literal multisets are identical; no type moved.handler?: UIEventHandlersits insideUIEventHandler's own declaration. The only.handlerreads tree-wide areJobPreview.tsx(d.handler) anduseKeyboardShortcuts.ts(shortcut.handler), and neither is a dialog actioncontent/docs,examples,apps,skillsand every CHANGELOG.APISchemahas no importing package5534973498§3 made the card wait untilCONTRACT_REVIEW_TIERanswered. It answers today: this record is served at it. The gate no longer holdsminor, with the**BREAKING**banner and**ADR-0049 disposition: remove.**.ActionDefis exported from@object-ui/core(ActionRunner.tsthroughexport * from './actions/index.js'), and the{ type: 'url', target }example is valid against it. No other pending changeset names these symbols.6051-gantt-…(flagged for namingindex.ts) stays trueAblation A (barrel lines restored): TS2578 ×2 in the pin plus TS2305 ×2; vitest 1 failed / 5 passed.
Ablation B (both files at base): TS2578 ×4; vitest 3 failed / 3 passed.
After restoring, the tree is clean. The tombstone mirrors objectui#8800's in
ai.ts/dist/ai.d.tsFixes #6497andClause-②: yesopen the body at line start. Every claim was reproduced, including the census counts, the ablation counts and the absence of an AGENTS.md 「ADR-0049 retirement」 sectionNo fixes owed.
Out of scope
api-types.tshas the same island shape:HTTPMethod,APIRequest,APIConfig,DataFetchConfig,DataFetchableSchema,ExpressionNodeSchemaandAPISchemahave zero tracked-file hits outside the module and the barrel. That is a census only, with no runtime probe. Noted, not filed. It is the obvious next ADR-0049 candidate for triage to size.domain:uiseat #1 · review · 2026-09-24T18:44Zrefactor(types): retire UIEventHandler and EventableSchema (objectui#…