Skip to content

Handoff: CreatorTrack realtime + notifications round, BUILT (awaiting review/merge)

Date: 2026-07-06. Branch feat/realtime-notifications (worktree ~/forge-suite-wt/feat/realtime-notifications, DB clone ct_feat_realtime_notifications, dev preview http://100.97.43.104:3062). 11 commits on top of main d11144f; combined tsc --noEmit clean; worktree clean; NOT merged, NOT deployed.

What shipped (3 parallel workers, one worktree)

Realtime (Worker B) - useWorkspaceChanges active poll 6s -> 3s (cursor endpoint 10-17ms). - Settings->General missing new workspace: WorkspaceSwitcher "+" never dispatched WORKSPACE_UPDATED_EVENT; fixed + refetch on modal open + on cursor advance. - Live-update wiring: CRM + Sales CRM clients wired; lib/changes.ts cursor now covers crm.* tables. Tasks/calendar/pages already live.

Notifications + invites (Worker A) - Invite consent: existing accounts get pending invite + bell notification with Accept/Decline (app/api/invites/[inviteId]/{accept,decline}); no more auto-add. Email-invite flow for no-account emails unchanged. - Notification center: NotificationsBell rewritten; category chips (invite/reminder/mention/assignment/system), actor, read state, full history (limit 200). - Assignment notifications from lib/tasks.ts; @mention typeahead (MentionAutocomplete.tsx in BlockList.tsx) fires mention notifications via block routes. - ~3s unread-count poll (lib/hooks/useNotificationsPoll.ts, separate from changes cursor). - Migrations: invite-consent + category schema; RLS fix so a recipient sees their own notification row pre-membership (20260706T235835).

Polish (Worker C) - "Someone edited": root cause = core.users self-only RLS nulling cross-user joins; fixed via lib/actor-names.ts (roster SECURITY DEFINER resolver) in activity/page-views/snapshots. Write path was always correct. - App page header icon now uses the sidebar's appGlyph (read-only), so top-of-app and sidebar match.

Follow-up round (Worker D, 3 more commits, now 14 ahead of main)

  • Actor avatars: *_avatar payload keys stamped at dispatch; NotificationsBell renders real photo with initials fallback. Migration 20260707T002030 adds o_invited_by_avatar to core.claim_workspace_invites (additive).
  • Live updates: goals + intake wired (app.intake_* added to changes cursor). Skipped with rationale: social (own 6s poll already), agents (cross-workspace list, no single-workspace cursor fits), business (ERPNext passthrough, no local table), finance (identity-scoped, no workspace_id), campaigns (fully server-rendered; would need a client wrapper, flagged as future work).
  • Poll merge REJECTED, kept two pollers: notifications are user-scoped/cross-workspace and the bell is global; changes cursor is workspace-scoped and per-page. Rationale documented inline in useNotificationsPoll.ts.

Review notes

  • Mention typeahead and avatar rendering not exercised in a real browser with a second account (API/DB-verified only). Single-word @Michael matching only.
  • Worker reports: forge/comms/results/realtime-notifications-worker-a.md, creatortrack-polish-worker-c.md.

URL: https://mkdocs.justinsforge.com/memory/handoffs/creatortrack-realtime-notifications-built-2026-07-06/