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
Observed while implementing #5878 (PR #5894). Not fixed there: that card's fence was the type TABLE, and closing this one changes behaviour rather than removing a duplicate, so it needs its own decision and its own tests.
The duplicate
#5878 converged the sys_activity.type -> FeedItem.type table onto record:activity's exported ACTIVITY_TYPE_TO_FEED_TYPE. The row -> FeedItem construction around it is still written twice:
packages/plugin-detail/src/renderers/recordActivityFeed.ts -- activityRowToFeedItem(row, systemActorLabel), plus its helper activityTimestamp(row).
packages/app-shell/src/views/RecordDetailView.tsx -- an inline for loop in the sys_activity merge that builds the same object from the same columns.
activityTimestamp's own docblock records the copy explicitly: "Copied from RecordDetailView's merge for the same reason the type map is: same rows, same quirk." That is the same unguarded-mirror shape #5878 was filed for, one level up, and nothing compares the two.
Three ways they already differ
Unknown types are silent here, loud there. The block distinguishes a type the table maps to undefined (a decision, returns quietly) from a type the table does not contain at all (an unmapped producer, warnUnknownActivityType fires once per value). The console merge tests only if (!feedType) continue;, so both collapse into a silent drop. The diagnostic record:activity drops every sys_activity.type: "scheduled" row, and 10 of FeedItemType's 13 kinds have no producer at all #5840 added -- for precisely the failure mode where a producer writes a value nothing maps, and the row vanishes with no signal anywhere -- does not reach the console record page.
Missing-timestamp fallback.activityTimestamp returns String(row.created_at ?? ''); the inline copy assigns when = row.created_at, which can be undefined. Different FeedItem.createdAt for a row with neither column.
The system-actor label. Two independently authored i18n lookups (detail.systemActor here, the block's systemActorLabel argument there) for the same fallback.
Converging the constructor is not a mechanical deletion. Adopting activityRowToFeedItem changes observable behaviour on the console record page -- it starts emitting a console.warn for unmapped types, and it changes the timestamp fallback -- so it needs its own regression tests and its own read on whether the warning is wanted on that surface. Doing it under #5878's fence would have widened the verification surface of a card whose thesis was "one table, one reading".
Suggested shape
Export activityRowToFeedItem from @object-ui/plugin-detail's entry point (the table is already exported there as of PR #5894, and app-shell already imports from that barrel -- no new dependency edge), have RecordDetailView call it, and pin the convergence with an identity spy rather than a value comparison, as #5878 did. Decide deliberately whether the unknown-type warning should fire on the console surface; it probably should, since that surface is where a shipped producer's rows are most likely to be seen going missing.
Observed while implementing #5878 (PR #5894). Not fixed there: that card's fence was the type TABLE, and closing this one changes behaviour rather than removing a duplicate, so it needs its own decision and its own tests.
The duplicate
#5878 converged the
sys_activity.type->FeedItem.typetable ontorecord:activity's exportedACTIVITY_TYPE_TO_FEED_TYPE. The row ->FeedItemconstruction around it is still written twice:packages/plugin-detail/src/renderers/recordActivityFeed.ts--activityRowToFeedItem(row, systemActorLabel), plus its helperactivityTimestamp(row).packages/app-shell/src/views/RecordDetailView.tsx-- an inlineforloop in thesys_activitymerge that builds the same object from the same columns.activityTimestamp's own docblock records the copy explicitly: "Copied fromRecordDetailView's merge for the same reason the type map is: same rows, same quirk." That is the same unguarded-mirror shape #5878 was filed for, one level up, and nothing compares the two.Three ways they already differ
undefined(a decision, returns quietly) from a type the table does not contain at all (an unmapped producer,warnUnknownActivityTypefires once per value). The console merge tests onlyif (!feedType) continue;, so both collapse into a silent drop. The diagnostic record:activity drops everysys_activity.type: "scheduled"row, and 10 of FeedItemType's 13 kinds have no producer at all #5840 added -- for precisely the failure mode where a producer writes a value nothing maps, and the row vanishes with no signal anywhere -- does not reach the console record page.activityTimestampreturnsString(row.created_at ?? ''); the inline copy assignswhen = row.created_at, which can beundefined. DifferentFeedItem.createdAtfor a row with neither column.detail.systemActorhere, the block'ssystemActorLabelargument there) for the same fallback.Why it was not folded into the #5878 fix
Converging the constructor is not a mechanical deletion. Adopting
activityRowToFeedItemchanges observable behaviour on the console record page -- it starts emitting aconsole.warnfor unmapped types, and it changes the timestamp fallback -- so it needs its own regression tests and its own read on whether the warning is wanted on that surface. Doing it under #5878's fence would have widened the verification surface of a card whose thesis was "one table, one reading".Suggested shape
Export
activityRowToFeedItemfrom@object-ui/plugin-detail's entry point (the table is already exported there as of PR #5894, andapp-shellalready imports from that barrel -- no new dependency edge), haveRecordDetailViewcall it, and pin the convergence with an identity spy rather than a value comparison, as #5878 did. Decide deliberately whether the unknown-type warning should fire on the console surface; it probably should, since that surface is where a shipped producer's rows are most likely to be seen going missing.Filed unassigned for triage.
Generated by Claude Code