⛔ Correction — I filed this card pointing the wrong way, ~20 minutes after opening it
The first version said RecordChatterComponentProps.feed?: RecordActivityComponentProps over-promises and offered "narrow the ObjectUI type" as route A. That is refused, and the reason is a maintainer principle I had not applied when I filed it:
我们的项目以 objectstack 协议为准,文档应该以实际实现为准。协议不正确的应该先修改协议。
(relayed with its source on objectui#8934, 5617613810.)
Measured in the PM seat on objectstack-ai/objectstack HEAD eabdd66f45f402eba0f8404a8a9de4a501fc83a6, packages/spec/src/ui/component.zod.ts:
// :1349
export const RecordChatterProps = strictObject({ … }, {
…
/** Feed configuration (delegates to RecordActivityProps) */
// :1366
feed: RecordActivityProps.optional().describe('Embedded activity feed configuration'),
…
});
bound to both names — :2948 'record:chatter': RecordChatterProps, :2962 'record:discussion': RecordChatterProps; RecordActivityProps is at :1248.
⇒ The ObjectUI type is right. feed?: RecordActivityComponentProps (packages/types/src/record-components.ts:257) is the protocol's twin, and narrowing it locally is exactly what the principle forbids. What is wrong is the renderer, which reads five of the members the protocol declares. Blocked-by: and the scope below are the rewrite.
Blocked-by: objectstack-ai/objectui#8934 · Restart-when: closed objectstack-ai/objectui#8934
Scope — the remainder objectui#8934 does not reach
objectui#8934 is being implemented on route 1: run applyFeedConfig on the chatter path before handing items to RecordActivityTimeline, the same call shape renderers/record-activity.tsx:219 uses. That makes four of the protocol's members live on this path: types, limit, showCompleted, unifiedTimeline.
It does not reach two more. applyFeedConfig handles the filter pipeline only.
| member |
why it stays unread after objectui#8934 |
evidence |
filterMode |
RecordActivityTimeline takes it as a component prop, never off config |
RecordActivityTimeline.tsx:187 destructures filterMode: controlledFilter; :212 const activeFilter = controlledFilter ?? internalFilter. RecordChatterPanel declares its own filterMode prop (:39) and forwards it (:163, :220) — but RecordChatterRenderer (renderers/record-chatter.tsx:54-70) passes none. So an authored feed.filterMode reaches nothing on either name. |
enableMentions |
read only on the record:activity renderer |
renderers/record-activity.tsx:123 (enableMentions: read('enableMentions')) and :240 (config.enableMentions !== false). Zero reads in RecordChatterPanel.tsx or RecordActivityTimeline.tsx. The chatter path's @-mentions come from the host discussion context — record-chatter.tsx:69 passes mentionSuggestions={discussion?.mentionSuggestions} unconditionally, so the affordance exists but the member that is supposed to gate it does not. |
aria |
⚠️ NOT MEASURED |
whoever picks this up owes the reading. |
The protocol declares both (RecordActivityProps, component.zod.ts:1248): filterMode seeds which slice the dropdown opens on, enableMentions gates the composer's @-autocomplete suggestions. ObjectUI's own record:activity registration publishes both — packages/plugin-detail/src/index.tsx:662 and :672, the latter describing exactly the behaviour the chatter path is missing:
Offer @-mention autocomplete in the composer, from the host discussion context's user list. Off withholds the suggestions.
On record:chatter / record:discussion, "off" withholds nothing.
Where this came from
Two independent measurements, both after objectui#8962 opened:
The review raised it as an under-enumeration defect in a description that is no longer being shipped. The description is reverting, so what survives is the underlying gap, which is this card.
Not a route list
There is only one direction consistent with the principle: make the renderer read what the protocol declares. The open question is aria, and whether filterMode on a panel whose filter dropdown is itself gated by showFilterToggle has a coherent meaning when the toggle is off — that is a design question for the implementer, not a contract choice.
⚠️ Whoever picks this up: read objectui#8934's landed shape first. If route 1's applyFeedConfig wiring happens to make either member live as a side effect, this card is smaller than it reads — the dev on that card was asked to report it if so.
Class
objectui#4631's family, but the opposite pole from objectui#8236: nothing here is live-by-accident through a rest-spread, and nothing here is a declaration to retire. The declarations are correct on all three faces that mirror the protocol; only the reader is short.
Generated by Claude Code
Blocked-by: objectstack-ai/objectui#8934·Restart-when: closed objectstack-ai/objectui#8934Scope — the remainder objectui#8934 does not reach
objectui#8934 is being implemented on route 1: run
applyFeedConfigon the chatter path before handing items toRecordActivityTimeline, the same call shaperenderers/record-activity.tsx:219uses. That makes four of the protocol's members live on this path:types,limit,showCompleted,unifiedTimeline.It does not reach two more.
applyFeedConfighandles the filter pipeline only.filterModeRecordActivityTimelinetakes it as a component prop, never offconfigRecordActivityTimeline.tsx:187destructuresfilterMode: controlledFilter;:212const activeFilter = controlledFilter ?? internalFilter.RecordChatterPaneldeclares its ownfilterModeprop (:39) and forwards it (:163,:220) — butRecordChatterRenderer(renderers/record-chatter.tsx:54-70) passes none. So an authoredfeed.filterModereaches nothing on either name.enableMentionsrecord:activityrendererrenderers/record-activity.tsx:123(enableMentions: read('enableMentions')) and:240(config.enableMentions !== false). Zero reads inRecordChatterPanel.tsxorRecordActivityTimeline.tsx. The chatter path's @-mentions come from the host discussion context —record-chatter.tsx:69passesmentionSuggestions={discussion?.mentionSuggestions}unconditionally, so the affordance exists but the member that is supposed to gate it does not.ariaThe protocol declares both (
RecordActivityProps,component.zod.ts:1248):filterModeseeds which slice the dropdown opens on,enableMentionsgates the composer's @-autocomplete suggestions. ObjectUI's ownrecord:activityregistration publishes both —packages/plugin-detail/src/index.tsx:662and:672, the latter describing exactly the behaviour the chatter path is missing:On
record:chatter/record:discussion, "off" withholds nothing.Where this came from
Two independent measurements, both after objectui#8962 opened:
5617990272), which measured thatrecord:activitypublishes 11 inputs while that PR's rewritten description accounted for 9;The review raised it as an under-enumeration defect in a description that is no longer being shipped. The description is reverting, so what survives is the underlying gap, which is this card.
Not a route list
There is only one direction consistent with the principle: make the renderer read what the protocol declares. The open question is
aria, and whetherfilterModeon a panel whose filter dropdown is itself gated byshowFilterTogglehas a coherent meaning when the toggle is off — that is a design question for the implementer, not a contract choice.applyFeedConfigwiring happens to make either member live as a side effect, this card is smaller than it reads — the dev on that card was asked to report it if so.Class
objectui#4631's family, but the opposite pole from objectui#8236: nothing here is live-by-accident through a rest-spread, and nothing here is a declaration to retire. The declarations are correct on all three faces that mirror the protocol; only the reader is short.
Generated by Claude Code