When unread spans categories or uncategorized channels, select the
parentId bucket with the highest summed unread score before position
tie-break within the bucket.
Co-authored-by: Cursor <[email protected]>
Filter message rows by channelId in _unreadForChannel after HyperDB find.
When every unread channel shares one category parentId, limit
_selectGuildChannelWithUnread to that category before position tie-break.
Co-authored-by: Cursor <[email protected]>
Clarify _selectGuildChannelWithUnread order in README: unread/mention score,
then lastChannelByGuild, then first text. Reference smokes
test:guild-unread-over-last-channel and test:guild-unread-channel-jump.
Co-authored-by: Cursor <[email protected]>
selectChannel calls _persistLastGuildChannel for savable channel types.
_selectGuildChannelWithUnread falls back to lastChannelByGuild when no
unread channels qualify, after permission check via _canViewChannel.
Unread-weighted channel pick from v0.8.115 remains unchanged when unread > 0.
Co-authored-by: Cursor <[email protected]>
_openGuild clears stale activeChannelId and calls _selectGuildChannelWithUnread
to open the text/thread/announcement channel with the highest mention-weighted
unread count before falling back to the first text channel.
setSearch records queries of at least two characters into user prefs via
_recordSearchRecent. view() exposes searchRecentQueries for the active guild.
Co-authored-by: Cursor <[email protected]>
Phase 146 (v0.8.111): setDiscoveryFilter is async and saves query,
sort, minMembers, and tag to discoveryExploreFilter prefs. Restore
on boot via _ingestDiscoveryExploreBaselineFromPrefs. Emits discovery
after filter updates.
Co-authored-by: Cursor <[email protected]>
Single API toggles voiceRosterMutedOnly and voiceRosterDeafenedOnly
together for Phase 141 combined sidebar filter chip.
Co-authored-by: Cursor <[email protected]>
Expose setVoiceRosterMutedOnly with USER_PREFS persistence, ingest
voiceRosterMutedOnly and discoveryExploreBaselineAt from prefs, and
record baselineAt when markDiscoveryExploreOpened runs. View adds
discoveryExploreBaseline, discoveryExploreBaselineAt, and
voiceRosterMutedOnly for Phase 139 UX (v0.8.104).
Co-authored-by: Cursor <[email protected]>
Phase 138 platform changes:
- Apply local voiceMedia mute/deafen to self roster row via myVoiceChannelId
(no protomux roundtrip required for sidebar indicators).
- Persist discoveryExploreBaseline through updateUserPrefs on Explore open.
- Ingest discoveryExploreBaseline from USER_PREFS on boot and prefs events.
Co-authored-by: Cursor <[email protected]>
- setThreadsPanelSort and threadsPanelSort in view
- refreshDiscoveryListingsFromMesh on setDiscoveryFilter
- discoveryMeshRefreshAt for Explore freshness
Co-authored-by: Cursor <[email protected]>
- setThreadsPanelParentFilter and view.threadsPanelParentFilter
- voiceStatesByChannel rows include presenceStatus from guild mesh
- maybeRefreshStaleSearch on selectChannel for forum channel switches
Co-authored-by: Cursor <[email protected]>
Add maybeRefreshStaleSearch() to re-run guild/forum mesh queries when
searchMeshMeta.fetchedAt is older than 90s and mesh is enabled.
Invoke after loadGuild so switching servers refreshes stale P2P search
hits without requiring a manual ↻ click.
Co-authored-by: Cursor <[email protected]>
Add refreshSearch() to re-run guild/forum mesh queries and stamp
searchMeshMeta.fetchedAt for stale UI indicators.
Persist guild online counts to USER_PREFS.guildPresenceCache (debounced
gossip) and merge remote cache on prefs ingest so companion rail presence
stays consistent across linked devices.
Expose presence row timestamps on guildPresenceSummary in view().
Co-authored-by: Cursor <[email protected]>
Persist USER_PREFS.companionLastGuildId on every loadGuild so the
companion restores the last server the user opened on any device.
Restore companionLastGuildId on companion session startup instead of
always picking the first guild in the list.
Track per-guild online counts in _guildPresenceSummary (updated on
presence gossip) and expose guildPresenceSummary on platform.view()
for the companion guild rail presence dots.
Co-authored-by: Cursor <[email protected]>
Add searchForumPostsWithMesh and _forumPostsFromMeshMessages to merge
local forum haystack hits with guild MESSAGE_SEARCH mesh responses via
pearcord-search.mergeForumSearchHits.
_resolveSearchResults uses mesh for forum scope and records
_lastSearchMeshMeta with scope forum for the desktop search UI.
Co-authored-by: Cursor <[email protected]>
mergeSearchHits accepts query for ranked enrichment; DB fallback uses
rankAndEnrichSearchHits. linkDevicePairCode accepts an external Hyperswarm
for smoke/live pairing without destroying the guest swarm early.
Co-authored-by: Cursor <[email protected]>
Builds guildSearchIndex into GUILD_SYNC payloads from memory or the
persisted GuildSearchIndexStore, and merges inbound slices into local
indexes on join so multi-device search stays warm after mesh connect.
Co-authored-by: Cursor <[email protected]>
Integrate GuildSearchIndexStore on platform startup and debounced persist
after message ingest. Expose getGuildSearchIndexMeta and view.searchIndexMeta
for smokes and UI diagnostics.
Co-authored-by: Cursor <[email protected]>
Add _resolveAuditExportFilter to merge guild schedule filter with user prefs.
setAuditLogExportFilter now writes filter into auditExportSchedule for mods.
Push signed audit CSV on member join via debounced _pushAuditCsvOnMemberJoinIfDue
when pushCsvOnMemberJoin is enabled.
Fix GUILD_SYNC member ingest to only emit member events for new roster rows and
trigger the same debounced CSV push when a peer was offline during MEMBER_JOIN
gossip. Expose auditExportScheduleFilter in view for UI schedule hints.
Co-authored-by: Cursor <[email protected]>
_runScheduledAuditExportIfDue now calls pushAuditExportCsvToMesh when
pushSignedCsvToMesh is enabled. View exposes auditExportCsvMeta for the
audit modal HMAC signature badge.
Co-authored-by: Cursor <[email protected]>
- dryRunDigestWebhookRelay and webhook preview on digest-relay hook dry-run
- refreshArchivePeerHealth with persist + GUILD_SYNC mesh push
- syncModDigestGroupDmFromMesh and modDigestGroupDmMeta on GUILD_SYNC bundle
- Signed CSV hook failure digest export with signatureValid
- Ingest mod digest meta for all members; open group DM for mods only
Co-authored-by: Cursor <[email protected]>
Add ensureModDigestGroupDmChannel and _postModDigestGroupDmSummary so hook
failure digest mesh sync can post to an auto-created mod group DM without
leaving guild mode. Requires two other moderators (manage guild/channels).
Restore guild session after DM posts. Extend hook failure notify prefs API
for mod digest group DM toggles.
Co-authored-by: Cursor <[email protected]>
- Sign relay handoffs with guild-derived secret for webhook/smtp plugins
- Verify signature on getLastDigestRelayHandoff (signatureValid)
- Apply health decay in archive peer picker
- Show signature status in server settings UI
Co-authored-by: Cursor <[email protected]>
Record digest relay handoffs, post digest summaries to configured inbox channels,
validate worker versions on announce, sync digestRelayHandoff on GUILD_SYNC,
and expose getLastDigestRelayHandoff (Phase 109 v0.8.73).
Co-authored-by: Cursor <[email protected]>
- listAuditArchiveFetchPeers returns meshConnected per member
- automationDigestExportSchedule timer and snapshot persistence
- GUILD_SYNC slices for schedule and snapshot metadata
- runOverdueAutomationSchedules includes digest export task
Co-authored-by: Cursor <[email protected]>
- fetchAuditExportArchiveFromMesh via RPC 72 request/response waiters
- Respond to audit-export-archive-request when local archive has entries
- getAutomationScheduleDashboard on view state
- runIntegrationWorkerTrial fans out MESSAGE_CREATE and requires sawMessageCreate
- Merge archive ingest resolves pending mesh fetch waiters
Co-authored-by: Cursor <[email protected]>
Expose getAutomationDeliveryMetrics, dryRunAutomodMessage with optional
memberRoles, and automationDeliveryMetrics on view for server settings.
Co-authored-by: Cursor <[email protected]>
Include receiptRetention in guild sync bundles and ingest on join. Expose
dryRunAutomationHook and dryRunAllAutomationHooks for server settings
preview without writing delivery receipts.
Co-authored-by: Cursor <[email protected]>
Wire pearcord-delivery-receipts to run enabled hooks on every APP_EVENT and
bot-bridged messageCreate. Successful deliveries gossip APP_EVENT_RECEIPT;
view exposes automationDelivery stats for server settings UI.
Co-authored-by: Cursor <[email protected]>
Hide channels denied via role or channel overwrite from view().channels,
guard selectChannel with memberCanViewChannel, and reassign activeChannelId
to the first visible text channel when the current selection becomes hidden
after loadGuild or permission gossip.
Co-authored-by: Cursor <[email protected]>
Bundle channelSettings (description + slowmode) and all topic-bearing channel
types in GUILD_SYNC; ingest into ChannelDescriptionStore on peer join. Push
mesh sync after topic/description edits. _participationMask applies channel
overwrites for send, voice join, and view.canPostInActiveChannel.
Integrate pearcord-channel-permissions: list/upsert/delete overwrites,
channel-effective _hasPerm/_myPermissions, GUILD_SYNC bundle, and mesh
ingest handlers. Requires MANAGE_CHANNELS on the active channel to edit.
Add setActivityImageFromBytes (256 KB image cap, __presence__ channel) and
readActivityImagePreview for UI thumbnails. Merges large/small image keys
into the current activity and reuses presence enrichment for P2P gossip.
Async _enrichPresenceActivity resolves large/small image keys via the
local attachments store before PRESENCE_UPDATE broadcast on guild and
contacts meshes. Updates self presence activity after enrichment.
Wire pearcord-activity buildActivityFeed into view(), extend setPresence and
add setActivity for Now Playing. Friend list rows include activity field.
Co-authored-by: Cursor <[email protected]>
Wire pearcord-server-folders into PearcordPlatform: createServerFolder,
assignGuildToFolder, collapse/rename/delete, and buildServerRailLayout on
view() as serverRail with folderColors. Persist via updateUserPrefs
serverFolders and emit user-prefs after saves.
Co-authored-by: Cursor <[email protected]>
joinVoiceChannel auto-upgrades lurkers to listen-only; joinVoiceListenOnly
is explicit. Blocks unmute, soundboard, screen share, and mic capture when
listen-only. View exposes canJoinVoiceListenOnly, voiceMedia.listenOnly,
and listenOnly on voiceStatesByChannel. Audit VOICE_JOIN_LISTEN.
Co-authored-by: Cursor <[email protected]>
Parse pearcord:// URLs, load guild or openGroupDM context, then
jumpToMessage for notification and share-link flows.
Co-authored-by: Cursor <[email protected]>
Add resolveMessageJump and jumpToMessage so the UI can navigate to
reply parents in other text/DM channels before scrolling and highlighting.
Co-authored-by: Cursor <[email protected]>
Wire pearcord-guild-roles for create/update/delete roles, member assignments,
_hasPerm enforcement, GUILD_SYNC role bundles, and view.guildCustomRoles for UI.
Co-authored-by: Cursor <[email protected]>
- _buildGuildSyncBundle includes full members[] from listMembers()
- _ingestGuildSync upserts member rows and emits member for UI refresh
- _pushGuildSyncToMesh runs when messages or members exist (not messages-only)
Late joiners and reconnecting peers receive roster + roles over live mesh.
Co-authored-by: Cursor <[email protected]>
Expose setGuildEmojiAllowedRoles for mods, _usableGuildEmojis/_usableEmojiMap
for picker rendering, and view fields usableGuildEmojis + guildEmojiRoleOptions.
emojisByPack and emojiMap respect member role restrictions. Phase 63 / v0.8.28.
Co-authored-by: Cursor <[email protected]>
Add _buildGuildSyncBundle (50 msgs/channel, attachment meta),
_pushGuildSyncToMesh on peer join and remote MEMBER_JOIN, and
_ingestGuildSync with channel/attachment/message dedupe.
Joining members receive prior channel history without per-message
replay. Phase 61 / v0.8.26.
Co-authored-by: Cursor <[email protected]>
Pass guild boost level into emojiRegistry.upsert for slot enforcement.
Expose getGuildEmojiSlots() and view.guildEmojiSlots for server settings UI.
Co-authored-by: Cursor <[email protected]>