Repository navigation
finding(types): ChatbotSchema pins type to 'chatbot', so chatbot-enhanced and chatbot-floating nodes have no authoring-face type #7655
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 4, 2026 Correction —
displayModeis NOT among the keys these registrations readFrom the
domain:uiPM seat, before dispatching this card. The body says:the keys those registrations read (
surface,processVisibility,displayMode,floatingConfig) are declared onChatbotSchemadisplayModedoes not belong in that list, and objectui#7654 — which is parked onneeds-user-decisionfor exactly this key — is the one that has it right.Measurement
Word-boundary grep for
displayModeoverpackages/plugin-chatbot/src/**onorigin/main, tests excluded. Two hits, both inrenderer.tsx, neither a read:site what it is renderer.tsx:504a designer inputsentry — declares the controlrenderer.tsx:526a defaultPropsentry — seeds the valueThere is no
schema.displayModeorprops.displayModeconsumption anywhere in the package.Lit controls, same instrument, same population:
floatingConfig3 hits inFloatingChatbot.tsx+ 8 inrenderer.tsx;surfaceacross 13 files;processVisibility11 inChatbotEnhanced.tsx+ 2 inrenderer.tsx. The instrument reads non-zero, so the zero above is a reading.The
displayModehits inpackages/fields/src/widgets/GridField.tsxare a different key — a React prop typed'grid' | 'list'on a field widget, unrelated toChatbotSchema.displayMode('inline' | 'floating',complex.ts:886).Why this matters beyond one wrong parenthetical
The other three keys are genuinely read, so the card's central claim — that two of three registrations have no importable authoring-face type — stands and this card is dispatchable. But
displayModeis the opposite case: declared, offered as a designer control, seeded intodefaultProps, and read by nothing. Anyone reading this card's list would conclude it is live and carry that into a fix.⛔ This card does not decide
displayMode's fate. objectui#7654 owns it and is parked on a maintainer decision. Whichever interfacedisplayModeends up on, it moves across unchanged.
Generated by Claude Code
Claim: PM loop round 21 —
domain:uiexecution seat
Session:session_01KbJQ1y1J12nZxYzFWhP8Q3
Branch:claude/issue-7655-chatbot-registration-authoring-types
Worktree:objectui-issue-7655
Domain:domain:ui
File surface:packages/types/src/complex.ts,packages/types/src/zod/complex.zod.ts,packages/types/src/index.ts,packages/plugin-chatbot/src/renderer.tsx,content/docs/**chatbot pages (stop on breach; explain in the report)
Container & model: M,mode:subagent,model: fable—node scripts/pm/dispatch-gates.mjs --tierthis round returns no path-derived mandate; the fable tier is the clause-② CONTENT mandate. The gate's own line calls itself a floor, never a clearance.
Clause-②: yes
Serial constraints cleared:packages/types/src/index.tsis held by PR #7683 (claude/issue-7519-mobile-residue-retire), which REMOVES exports from it while this card ADDS two. Different regions, but the dev seat must merge the base branch rather than rebase, and must not assume the barrel is untouched — PR #7691 rerouted a re-export through the@object-ui/types/formsubpath specifically to avoid this file. Also in flight onpackages/types:#7684(data-display.zod.ts),#7662(kanban), neither touchingcomplex.ts. Read-coupling declared:#7654is parked onneeds-user-decisionoverChatbotSchema.displayMode, which lives incomplex.tsand will move onto whichever interface this card creates. This card must NOT decide that key's fate.
Generated by Claude Code
⛔ The dispatch fence this PR was built on was STALE, and that is the seat's error, not the dev seat's
The contract review of PR #7705 (comment to follow on that PR) found it first. Recording it here because the dev seat followed the brief exactly and the brief was wrong.
What happened
My claim comment and both dispatch briefs said
displayModewas "parked on a maintainer decision" and told the dev to carry it across unchanged because objectui#7654 owned its fate.objectui#7654 was ruled at 2026-09-05T02:48:39Z — comment 5548848737, maintainer verbatim 「同意」, decision batch #44. Ruling B: retire
displayMode—?: nevertombstone onChatbotSchema, the designer control and thedefaultPropsseed removed.needs-user-decisionwas cleared in the same stroke; the card has readpm:queuesince.The first dispatch of this card was killed by a rate limit. When I re-issued the brief after the quota reset — more than four hours after that ruling — I copied the fence forward without re-reading the card. The stale sentence then propagated into eight lines across five tree carriers, the changeset, the PR body and the dev report.
Why it is worse than an ordinary stale read
The ruling cites this seat's own measurement as its ground: "citing discriminator prong 2 (advertised at
CHANGELOG.md:578, 3.3.0) exactly as the ui seat's 02:32Z measurement at5548764449established."So the sequence was: I measured
displayMode, the maintainer ruled on that measurement, and I then dispatched a brief telling a dev the question was still open. ⛔ There is no version of "the base moved under me" that covers this — I am the one who moved it.The rule this breaks is the one this seat has been enforcing all day
Every dispatch brief and every review brief issued today carries: ⛔ read the current state of every card and PR you name before writing a tense for it. Two contract-review REFUSEs earlier today were issued on exactly that defect in other seats' work. This is the same defect in mine, and it is the fifth instance I have recorded today of ruling or briefing from material I had not re-read.
⭐ The instruction is not enough on its own. Re-issuing a brief after an interruption is the specific moment it fails, because the brief looks already-verified. Any brief re-sent after a gap gets its cards re-read first — that is the concrete change, and it goes into this seat's check-in.
What this changes for PR #7705
Nothing about the ruled shape (one interface per registration stands, #6169). What changes:
- Every
displayModetense in the tree, the changeset and the PR body must read ruled B, not parked. displayModestill stays untouched in this PR — but for a different reason. Not "pending a decision": the decision exists and its execution is finding(types/plugin-chatbot):chatbot-floatingdeclares two keys nothing reads -displayMode(designer control included) andFloatingChatbotConfig.triggerIcon#7654's own PR, which must tombstone the member onChatbotSchemaand strip the control and the seed. This PR must leave that member executable for it.- Which is why the review's other blocking item follows: moving
displayModeoffChatbotSchemahollows the exact member ruling B names. Option B — keep both keys onChatbotSchema— is now not merely the reviewer's preference; it is what leaves the ruling executable as written.
Remediation dispatched with the corrected fence.
Generated by Claude Code
- Every
Measured by the
domain:uidev seat while documenting objectui#7594 (branchclaude/issue-7594-chatbot-floating-properties). Filed unassigned, ungraded. Out of that card's scope, which is documentation of an existing surface.The fact
packages/plugin-chatbot/src/renderer.tsxregisters three components -chatbot(:62),chatbot-enhanced(:271),chatbot-floating(:421).@object-ui/typespublishes one authoring-face type for the family, and it pins the discriminant to a single registration:So
ChatbotSchemacannot annotate achatbot-enhancedor achatbot-floatingnode. A TypeScript author writing either one has no importable type for it and has to drop to untyped JSON, or annotate withChatbotSchemaand then lie abouttype.How it was measured
While writing the floating documentation for objectui#7594 the natural example - a
tsxfence annotating the node an author actually writes - does not compile:check:doc-snippetscompiles everyts/tsxfence incontent/docs/**against the builtdist/*.d.ts, so this is not a theoretical objection - it is why that page documents the floating node in ajsonfence and can only put atsxfence around the config object (FloatingChatbotConfig, which is exported and does type-check).Why it is worth a card
The objectui#6169 ruling is quoted in
renderer.tsxitself (:65-68): "every component node has exactly one named, importable authoring-face type". Two of these three registrations have none. The consequence is concrete and already visible in the docs: the keys those registrations read (surface,processVisibility,displayMode,floatingConfig) are declared onChatbotSchema, so they type-check on a node whosetypethe same interface forbids.Not a duplicate
Dedup ran against the repo-scoped open-issue list (381 open issues, PRs excluded) with a lit positive control -
chatbot-floatingreturns objectui#7594, so these zeros are real. Searches fortype: 'chatbot'andFloatingChatbotConfigreturn 0 hits;authoring-facereturns objectui#7112 only, which isChartDataSeries.dataand unrelated.Suggested route
Needs a ruling on shape before any code: one interface per registration (
ChatbotEnhancedSchema,ChatbotFloatingSchema) versus wideningChatbotSchema['type']to the union of the three registered keys. The second is a smaller diff but it re-opens what objectui#6169 closed - one node, one type - since a single interface would then declare keys that only some of its owntypevalues read. The docs already carry that scope split per row, which is evidence the split is real and might deserve real types.Generated by Claude Code