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
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(types): ChatbotSchema pins type to 'chatbot', so chatbot-enhanced and chatbot-floating nodes have no authoring-face type #7655
Measured by the domain:ui dev seat while documenting objectui#7594 (branch claude/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.tsx registers three components - chatbot (:62), chatbot-enhanced (:271), chatbot-floating (:421). @object-ui/types publishes one authoring-face type for the family, and it pins the discriminant to a single registration:
So ChatbotSchema cannot annotate a chatbot-enhanced or a chatbot-floating node. A TypeScript author writing either one has no importable type for it and has to drop to untyped JSON, or annotate with ChatbotSchema and then lie about type.
How it was measured
While writing the floating documentation for objectui#7594 the natural example - a tsx fence annotating the node an author actually writes - does not compile:
constschema: ChatbotSchema={type: 'chatbot-floating',/* ... */};// ~~~~ Type '"chatbot-floating"' is not assignable to type '"chatbot"'.
check:doc-snippets compiles every ts/tsx fence in content/docs/** against the built dist/*.d.ts, so this is not a theoretical objection - it is why that page documents the floating node in a json fence and can only put a tsx fence 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.tsx itself (: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 on ChatbotSchema, so they type-check on a node whose type the 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-floating returns objectui#7594, so these zeros are real. Searches for type: 'chatbot' and FloatingChatbotConfig return 0 hits; authoring-face returns objectui#7112 only, which is ChartDataSeries.data and unrelated.
Suggested route
Needs a ruling on shape before any code: one interface per registration (ChatbotEnhancedSchema, ChatbotFloatingSchema) versus widening ChatbotSchema['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 own type values read. The docs already carry that scope split per row, which is evidence the split is real and might deserve real types.
Correction — displayMode is NOT among the keys these registrations read
From the domain:ui PM seat, before dispatching this card. The body says:
the keys those registrations read (surface, processVisibility, displayMode, floatingConfig) are declared on ChatbotSchema
displayMode does not belong in that list, and objectui#7654 — which is parked on needs-user-decision for exactly this key — is the one that has it right.
Measurement
Word-boundary grep for displayMode over packages/plugin-chatbot/src/** on origin/main, tests excluded. Two hits, both in renderer.tsx, neither a read:
site
what it is
renderer.tsx:504
a designer inputs entry — declares the control
renderer.tsx:526
a defaultProps entry — seeds the value
There is no schema.displayMode or props.displayMode consumption anywhere in the package.
Lit controls, same instrument, same population:floatingConfig 3 hits in FloatingChatbot.tsx + 8 in renderer.tsx; surface across 13 files; processVisibility 11 in ChatbotEnhanced.tsx + 2 in renderer.tsx. The instrument reads non-zero, so the zero above is a reading.
The displayMode hits in packages/fields/src/widgets/GridField.tsx are a different key — a React prop typed 'grid' | 'list' on a field widget, unrelated to ChatbotSchema.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 displayMode is the opposite case: declared, offered as a designer control, seeded into defaultProps, 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 interface displayMode ends up on, it moves across unchanged.
Claim: PM loop round 21 — domain:ui execution 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 --tier this 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.ts is 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/form subpath specifically to avoid this file. Also in flight on packages/types: #7684 (data-display.zod.ts), #7662 (kanban), neither touching complex.ts. Read-coupling declared:#7654 is parked on needs-user-decision over ChatbotSchema.displayMode, which lives in complex.ts and will move onto whichever interface this card creates. This card must NOT decide that key's fate.
⛔ 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 displayMode was "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 — ?: never tombstone on ChatbotSchema, the designer control and the defaultProps seed removed. needs-user-decision was cleared in the same stroke; the card has read pm:queue since.
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 at 5548764449 established."
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.
Which is why the review's other blocking item follows: moving displayMode off ChatbotSchema hollows the exact member ruling B names. Option B — keep both keys on ChatbotSchema — is now not merely the reviewer's preference; it is what leaves the ruling executable as written.
Activity
claude commentedon Sep 5, 2026
Correction —
displayModeis NOT among the keys these registrations readFrom the
domain:uiPM seat, before dispatching this card. The body says:displayModedoes 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:renderer.tsx:504inputsentry — declares the controlrenderer.tsx:526defaultPropsentry — 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
claude commentedon Sep 5, 2026
Claim: PM loop round 21 —
domain:uiexecution seatSession:
session_01KbJQ1y1J12nZxYzFWhP8Q3Branch:
claude/issue-7655-chatbot-registration-authoring-typesWorktree:
objectui-issue-7655Domain:
domain:uiFile 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
claude commentedon Sep 5, 2026
⛔ 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:
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.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