feat(platform): pick guild channel by parent unread bucket total

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]>
This commit is contained in:
Raven Scott
2026-05-22 18:34:52 -04:00
co-authored by Cursor
parent f7c795259f
commit eea4ce0187
2 changed files with 23 additions and 0 deletions
+2
View File
@@ -135,6 +135,8 @@ Primary consumer: `apps/pearcord/index.js` sidecar reading pear-pipe JSON.
**v0.8.115:** `loadGuild` / `_openGuild` clears stale `activeChannelId`, then `_selectGuildChannelWithUnread` picks mention-weighted unread channels before falling back to the first text channel. `setSearch` records `searchRecentByGuild` in user prefs. View: `searchRecentQueries`.
**v0.8.125:** `_selectGuildChannelWithUnread` picks the parent bucket (category or uncategorized) with the highest total unread score, then best channel within it. Smokes: `test:guild-category-bucket-pick`, `test:guild-category-unread-pick`.
**v0.8.124:** `_unreadForChannel` filters rows by `channelId` after HyperDB find. When all unread are in one category, `_selectGuildChannelWithUnread` picks only within that `parentId`. Smoke: `test:guild-category-unread-pick`.
**v0.8.123:** Equal unread/mention scores tie-break to lower `channel.position`. Smoke: `test:guild-unread-position-tie`.
+21
View File
@@ -5074,6 +5074,27 @@ class PearcordPlatform extends EventEmitter {
if (categoryParents.size === 1 && !hasUncategorizedUnread) {
const parentId = [...categoryParents][0]
pool = scored.filter((r) => r.ch.parentId === parentId)
} else if (categoryParents.size > 0 || hasUncategorizedUnread) {
const buckets = new Map()
for (const row of scored) {
const key = row.ch.parentId || ''
if (!buckets.has(key)) buckets.set(key, { rows: [], total: 0, minPos: Infinity })
const bucket = buckets.get(key)
bucket.rows.push(row)
bucket.total += row.score
bucket.minPos = Math.min(bucket.minPos, row.ch.position || 0)
}
let winBucket = null
for (const bucket of buckets.values()) {
if (
!winBucket ||
bucket.total > winBucket.total ||
(bucket.total === winBucket.total && bucket.minPos < winBucket.minPos)
) {
winBucket = bucket
}
}
if (winBucket) pool = winBucket.rows
}
let best = null
let bestScore = -1