docs(guide): quick-start teaches the action:button node, not the unread events bag - #7949
Merged
Merged
Conversation
The Next Steps -> Add Actions section declared the `events` bag as THE way to
author actions ("Define them in schema events:") and showed a `button` node
carrying `events.onClick`. Nothing reads that key.
Measured on this tree:
git grep -nE '\??\.events\b' -- 'packages/*/src' 'apps/*/src' -> 0 hits
git grep -n 'EventableSchema' -- packages apps -> exactly 3:
packages/types/src/api-types.ts:278 own declaration (a TS interface)
packages/types/src/api-types.ts:470 one union member
packages/types/src/index.ts:729 barrel re-export
no extender, no mirror, no reader.
`packages/core/src/utils/dom-props.ts:24` cites `events="[object Object]"` as an
example of the DOM leak its pass-through whitelist exists to close, and the
`handlerKeyRefusal` remedy string points authors at a NODE TYPE ("an
action:button node with a declared action"), never at the bag. The bag is an
authored key an interface declares and `.passthrough()` keeps, not a channel:
objectui#6182's 2026-08-25 Option A ruling re-priced it to an ADR-0049
retirement.
Prose and fence are replaced together, since fixing only the fence would move
the contradiction rather than remove it. The replacement is the landed dialect
(objectui#7898 / PR objectui#7931): an `action:button` node whose `actionType`
names the executor and whose `target` carries the location.
Spelling measured against the BUILT artifacts, not carried over from the
ButtonSchema sweep:
node_modules/@objectstack/spec/dist/action.zod-CLgwKXBA.d.ts:275-282
ActionType = url | form | flow | script | api | modal
packages/types/dist/ui-action.d.ts:168,191,202
RunnableActionType = ActionType | 'navigation' ('navigation' is
objectui's own alias of `url`; the source note prefers `url`)
packages/types/dist/ui-action.d.ts, interface UIActionSchema
target?: string -- "the **only** handler slot"
packages/core/src/actions/ActionRunner.ts:1418
executeUrl reads `action.target || action.redirect` (not params.url)
packages/components/src/renderers/action/action-button.tsx:160,166
forwards `type: schema.actionType` and `target: schema.target`
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7936
Clause-②:
no— docs example only: no key added, no zod touched, no gate predicate or scan population moved.content/docs/guide/quick-start.md, Next Steps → Add Actions, declared theeventsbag as THE way to author actions ("Define them in schema events:") and showed abuttonnode carryingevents.onClick. Nothing reads that key. Prose and fence are replaced together — fixing only the fence would move the contradiction rather than remove it.The four evidence items, reproduced on this worktree (base
b8e3f8379)A — SDUI read points: zero.
B —
EventableSchema: exactly three sites, no extender / mirror / reader.(The card recorded the re-export at
index.ts:718; on this base it sits at:729. Substance identical — one declaration, one union member, one barrel re-export.)EventableSchemais a TypeScript interface inapi-types.ts, not a zod schema. An authoredeventsbag survivessafeParsebecauseButtonSchema/BaseSchemaare.passthrough(). The accurate statement is declared on the TS face, exported from the barrel, read by nothing at runtime.C — the DOM pass-through whitelist cites this very key as a leak.
D — the refusal message points at a node type, never at the bag.
ButtonSchema(packages/types/src/zod/form.zod.ts:160) declaresonClick: handlerKeyRefusal('onClick', 'runtime-slot', 'Click handler')(:174), whose remedy string inpackages/types/src/zod/tombstone.zod.ts:118-120reads:Surface: exactly one file, and that is measured
The two
schema-reference.mdhits aretimeline's owneventsarray, which has a real reader — not a defect, not touched (the card recorded them at:669,1092; same two occurrences, drifted line numbers). One file changed:content/docs/guide/quick-start.md, 7 insertions, 12 deletions.The replacement spelling was measured against the BUILT artifacts
Not carried over from the
ButtonSchemasweep —ActionSchemaandaction:buttonwere measured on their own declarations.node_modules/@objectstack/spec/dist/action.zod-CLgwKXBA.d.ts:275-282ActionType=url | form | flow | script | api | modalpackages/types/dist/ui-action.d.ts:168,191,202RunnableActionType = ActionType | ObjectUiLocalActionType,ObjectUiLocalActionType = 'navigation'— objectui's own alias ofurl; the source note says "Prefertype: 'url'+openInin new metadata"packages/types/dist/ui-action.d.ts,interface UIActionSchematarget?: string— "the only handler slot";openIn?: 'self' | 'new-tab'packages/core/src/actions/ActionRunner.ts:1418executeUrlreadsaction.target || action.redirect— notparams.urlpackages/components/src/renderers/action/action-button.tsx:160,166type: schema.actionType,target: schema.targetSo the intent of the old example (navigate to
/users/ada) is authored asactionType: "url"+target: "/users/ada"on anaction:buttonnode — the dialect already landed incontent/docs/guide/record-edit-modes.md:66-110.Reverse verification (planted-failure direction, run against the built
packages/types/dist):Exactly one error, the planted one:
'url'compiles,'navigate'— the action name the old fence taught — does not, andtargetaccepts the path. The probe file was deleted before the commit (git statusclean, only the one doc file modified).Gates — all run on the final commit
ca586a664,git diff HEADemptyDerived from the changed path by
grep -rln "content/docs" scripts/*.mjs(every gate script whose population readscontent/docs), plus the checks the dispatch named.check:doc-types✅ Every documented component type is registered.(889typeliterals, 772 registered, 117 exempted — identical to the pre-edit baseline)check:doc-fences✅ check:doc-fences — every TypeScript block in 227 document(s) is fenced ts/tsx/typescript…check-doc-linksLinks are valid across 17 scan roots.check-doc-expression-carriagecheck:control-bytes✅ check-control-bytes: OK (scanned 6407 tracked text file(s); skipped 85 binary).check:doc-snippetsEvery covered documentation snippet compiles against the built types.(467/467 judged, 0 failed)check:skill-examplesEvery marked skill example holds up against the built types.check:doc-example-readersOK 80 documented symbol(s), 3947 call site(s)…check:docs-route-closurecheck:shell-escape-residue✅ check-shell-escape-residue: OK (5/5 root(s) resolved…)check:skills-pathscheck:doc-snippetsandcheck:skill-examplesboth exit 2 (PREREQUISITE NOT MET, not a verdict) on an unbuilt tree; both were run after building this gate's own--build-filterclosure —turbo run build … --concurrency=2, 34/34 tasks successful, through the container's shared verify lock (VERDICT command-exit 0 · held the lock 208s · waited 51s).check-doc-expression-carriagecensus, before and after — identical, as expected (both fences are literals, outside its population):Changeset — quoted verbatim from
node scripts/check-changeset-presence.mjs(exit 0), and obeyed:No
skip-changesetlabel applied: in this repository that label is read by nothing, and the checker's verdict line is the authority.Deliberately not touched
content/docs/api/schema-reference.md—timeline's ownevents, real reader.content/docs/core/enhanced-actions.mdx— itsactionType: 'ajax'andapi:are legal forActionSchema, and that was measured rather than assumed:packages/types/src/zod/crud.zod.ts:64-71declarestype: z.literal('action')withactionType: z.enum(['button','link','dropdown','ajax','confirm','dialog'])andapi: z.string().optional(). A different schema fromButtonSchema, with its own vocabulary. Not a defect; not changed.Learn the full action model in [Enhanced Actions]line below the fence — outside the declared surface.Out-of-scope finding filed
#7945 — the published
skills/objectuiskill (SKILL.md,guides/page-builder.md,rules/protocol.md) andAGENTS.mdstill teach the sameeventsbag across 5 sites, one of them worded as a Rule on a customer-published surface. Both are governance surfaces this seat must not edit, so it is reported, not fixed. That issue is filed with no assignee and is not addressed here.Generated by Claude Code