docs: Phase 185 v0.8.150 roadmap, search, channels, notifications, guild

Document field Escape activedescendant clear, text+forum labels, status
role create smoke, and triple combo bucket pick. Plan Phase 186.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-05-22 20:17:35 -04:00
co-authored by Cursor
parent b2e3aff610
commit a626c6c0a9
10 changed files with 47 additions and 16 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# Pearcord architecture
**Current release:** v0.8.149 (desktop app `apps/pearcord`). Phase history and checklists live in [PLATFORM_ROADMAP.md](./PLATFORM_ROADMAP.md). Gap vs a centralized chat product is tracked in [PEARCORD_PARITY.md](./PEARCORD_PARITY.md).
**Current release:** v0.8.150 (desktop app `apps/pearcord`). Phase history and checklists live in [PLATFORM_ROADMAP.md](./PLATFORM_ROADMAP.md). Gap vs a centralized chat product is tracked in [PEARCORD_PARITY.md](./PEARCORD_PARITY.md).
Pearcord is a **100% peer-to-peer** community chat client on [Pear](https://pear.holepunch.to) / Bare. There is no Pearcord-operated message server: guilds, DMs, discovery listings, and bot events replicate over **Hyperswarm** topics with **protomux** framing.
+5 -1
View File
@@ -462,7 +462,11 @@ Pearcord validates itself without manual QA.
| `npm run test:channel-category-text-thread-label` | Text+thread label (`CHANNEL_CATEGORY_TEXT_THREAD_LABEL_SMOKE_OK`) |
| `npm run test:notif-mark-all-status-aria-label` | Status aria-label assert (`NOTIF_MARK_ALL_STATUS_ARIA_LABEL_SMOKE_OK`) |
| `npm run test:guild-combo-bucket-minpos-tie` | Combo minPos tie (`GUILD_COMBO_BUCKET_MINPOS_TIE_SMOKE_OK`) |
| `npm run test:boot` | `pear run` pre-run (`BOOT_OK`) then Phase 124184 smokes + `test:companion-boot` |
| `npm run test:search-recent-chip-field-escape` | Field Escape clear (`SEARCH_RECENT_CHIP_FIELD_ESCAPE_SMOKE_OK`) |
| `npm run test:channel-category-text-forum-label` | Text+forum label (`CHANNEL_CATEGORY_TEXT_FORUM_LABEL_SMOKE_OK`) |
| `npm run test:notif-mark-all-status-role-create` | Status role create (`NOTIF_MARK_ALL_STATUS_ROLE_CREATE_SMOKE_OK`) |
| `npm run test:guild-triple-combo-bucket-pick` | Triple combo buckets (`GUILD_TRIPLE_COMBO_BUCKET_PICK_SMOKE_OK`) |
| `npm run test:boot` | `pear run` pre-run (`BOOT_OK`) then Phase 124185 smokes + `test:companion-boot` |
| `npm run test:server-folder-prefs-mesh` | Live folder prefs mesh (optional; run manually — can exceed 150s on DHT) |
| `npm run test:profile` | Profile update + persist (`PROFILE_SMOKE_OK`) |
| `npm run test:e2e` | Full journey host+guest (`E2E_SMOKE_OK`) |
+1
View File
@@ -23,6 +23,7 @@ Gossip: existing `RPC.CHANNEL_CREATE` carries full channel row including `parent
## UI
- Mixed text+forum categories include separate text and forum counts in `aria-label` (v0.8.150). Smoke: `npm run test:channel-category-text-forum-label`.
- Mixed text+thread categories include separate text and thread counts in `aria-label` (v0.8.149). Smoke: `npm run test:channel-category-text-thread-label`.
- Thread-only categories use “thread channel(s)” in `aria-label`; category child lists include `thread` rows (v0.8.148). Smoke: `npm run test:channel-category-thread-label`.
- Text-only categories use “text channel(s)” in `aria-label` (v0.8.147). Smoke: `npm run test:channel-category-text-label`.
+1 -1
View File
@@ -1,6 +1,6 @@
# Pearcord documentation index
All project documentation lives in **`pearcord-docs`** (`/Users/raven/dev/pearcord/docs/`). **Release:** v0.8.149.
All project documentation lives in **`pearcord-docs`** (`/Users/raven/dev/pearcord/docs/`). **Release:** v0.8.150.
| Start here | Document |
|------------|----------|
+2 -2
View File
@@ -31,7 +31,7 @@ JSON lines over `pear-pipe` between `ui/app.js` and `apps/pearcord/index.js`. Ha
### Channel pick order (`select-guild` / `loadGuild`)
When a guild opens, `pearcord-platform` `_selectGuildChannelWithUnread` chooses the active text/forum/thread/announcement channel in this order (v0.8.149):
When a guild opens, `pearcord-platform` `_selectGuildChannelWithUnread` chooses the active text/forum/thread/announcement channel in this order (v0.8.150):
1. **Unread + mentions** — score `mentions × 1000 + unread` per channel. Pool selection:
- If every unread channel shares one category (`parentId`), only channels in that category compete (mention-weighted score, then lower `position` on ties). Smokes: `test:guild-single-category-pool`, `test:guild-mention-single-category-pick`, `test:guild-dual-category-isolation-pick`.
@@ -39,7 +39,7 @@ When a guild opens, `pearcord-platform` `_selectGuildChannelWithUnread` chooses
2. **`lastChannelByGuild`** — USER_PREFS last viewed channel for this guild when valid and viewable.
3. **First text channel** — lowest-position `text` channel, else first candidate.
Smokes: `test:guild-channel-pick-order` (IPC + platform source), `test:guild-unread-position-tie`, `test:guild-in-bucket-position-tie`, `test:guild-mention-in-bucket-pick`, `test:guild-mention-single-category-pick`, `test:guild-dual-category-isolation-pick`, `test:guild-mixed-bucket-pick`, `test:guild-mention-root-bucket-pick`, `test:guild-root-mention-bucket-pick`, `test:guild-mention-triple-bucket-pick`, `test:guild-root-plain-triple-mention-pick`, `test:guild-mention-plain-bucket-pick`, `test:guild-dual-combo-bucket-pick`, `test:guild-combo-beats-plain-equal`, `test:guild-combo-bucket-minpos-tie`, `test:guild-bucket-minpos-root-pick`, `test:guild-bucket-minpos-order-pick`, `test:guild-bucket-minpos-triple-pick`, `test:guild-bucket-total-over-minpos`, `test:guild-uncategorized-bucket-pick`, `test:guild-single-category-pool`, `test:guild-category-unread-pick`, `test:guild-category-bucket-pick`, `test:guild-mention-bucket-pick`, `test:guild-bucket-minpos-tie`, `test:guild-mention-channel-pick`, `test:guild-unread-over-last-channel`, `test:guild-last-channel-only-load`, `test:guild-no-unread-last-channel`, `test:guild-first-text-fallback`.
Smokes: `test:guild-channel-pick-order` (IPC + platform source), `test:guild-unread-position-tie`, `test:guild-in-bucket-position-tie`, `test:guild-mention-in-bucket-pick`, `test:guild-mention-single-category-pick`, `test:guild-dual-category-isolation-pick`, `test:guild-mixed-bucket-pick`, `test:guild-mention-root-bucket-pick`, `test:guild-root-mention-bucket-pick`, `test:guild-mention-triple-bucket-pick`, `test:guild-root-plain-triple-mention-pick`, `test:guild-mention-plain-bucket-pick`, `test:guild-dual-combo-bucket-pick`, `test:guild-triple-combo-bucket-pick`, `test:guild-combo-beats-plain-equal`, `test:guild-combo-bucket-minpos-tie`, `test:guild-bucket-minpos-root-pick`, `test:guild-bucket-minpos-order-pick`, `test:guild-bucket-minpos-triple-pick`, `test:guild-bucket-total-over-minpos`, `test:guild-uncategorized-bucket-pick`, `test:guild-single-category-pool`, `test:guild-category-unread-pick`, `test:guild-category-bucket-pick`, `test:guild-mention-bucket-pick`, `test:guild-bucket-minpos-tie`, `test:guild-mention-channel-pick`, `test:guild-unread-over-last-channel`, `test:guild-last-channel-only-load`, `test:guild-no-unread-last-channel`, `test:guild-first-text-fallback`.
| `select-channel` | `channelId` | Set active text channel (voice IDs join voice) |
| `join-voice` | `channelId` | Join voice channel + gossip |
+1
View File
@@ -23,6 +23,7 @@ Skipped when:
- **Channel list** — existing unread + `@` pills
- **🔔 header** — inbox panel, prefs, mark all read; **click row jumps to message** (v0.8.35+)
- **Mark all read** — dedicated header button when unread rows exist (v0.8.115); smoke: `npm run test:notif-mark-all-header`
- **Status role create (v0.8.150)** — dedicated smoke asserts `banner.setAttribute('role', 'status')` on create (not `alert`). Smoke: `npm run test:notif-mark-all-status-role-create`
- **Status aria-label assert (v0.8.149)** — dedicated smoke asserts `banner.setAttribute('aria-label', 'All notifications marked as read')` on create. Smoke: `npm run test:notif-mark-all-status-aria-label`
- **Status aria-relevant assert (v0.8.148)** — dedicated smoke asserts `banner.setAttribute('aria-relevant', 'additions')` only on create. Smoke: `npm run test:notif-mark-all-status-aria-relevant`
- **Status aria-atomic assert (v0.8.147)** — dedicated smoke asserts `banner.setAttribute('aria-atomic', 'true')` on create in `onMarkAllNotifClick`. Smoke: `npm run test:notif-mark-all-status-aria-atomic`
+13 -4
View File
@@ -4,14 +4,23 @@ Gap analysis between **Pearcord** (P2P Pear app) and a typical **centralized cha
> This is the only doc that compares against an external reference product. All other docs use Pearcord naming only.
## Summary (v0.8.150)
| Area | Reference product | Pearcord | Gap |
|------|-------------------|----------|-----|
| Search | Recent queries | Field nav + Escape clear | Escape+filter order (P186); no cloud |
| Channels | Categories | Text/thread/forum/voice/stage labels | Text+announcement label (P186) |
| Notifications | Inbox | Status role + live + atomic + relevant + label | Status labelledby smoke (P186) |
| Guild open | Channel pick | Triple combo bucket totals | Plain over lower combo (P186) |
## Summary (v0.8.149)
| Area | Reference product | Pearcord | Gap |
|------|-------------------|----------|-----|
| Search | Recent queries | Field activedescendant + Home/End/Page | Escape clears field descendant (P185); no cloud |
| Channels | Categories | Text/thread/voice/stage/forum labels | Mixed text+forum label (P185) |
| Notifications | Inbox | Status full a11y bundle on create | Status role dedicated smoke (P185) |
| Guild open | Channel pick | Combo minPos tie-break | Triple combo buckets (P185) |
| Search | Recent queries | Field activedescendant + Home/End/Page | Escape clears field descendant (done P185); no cloud |
| Channels | Categories | Text/thread/voice/stage/forum labels | Mixed text+forum label (done P185) |
| Notifications | Inbox | Status full a11y bundle on create | Status role dedicated smoke (done P185) |
| Guild open | Channel pick | Combo minPos tie-break | Triple combo buckets (done P185) |
## Summary (v0.8.148)
+20 -6
View File
@@ -946,16 +946,29 @@ When completing work, change `[ ]` → `[x]` and add a one-line note under **Cha
---
### Phase 185 — Search & guild polish (planned)
### Phase 185 — Search & guild polish (v0.8.150)
| ID | Item | Status |
|----|------|--------|
| P185-1 | Search: Escape clears field `aria-activedescendant` when chips visible | [ ] |
| P185-2 | Channels: mixed text+forum category label counts | [ ] |
| P185-3 | Notifications: mark-all status `role="status"` dedicated smoke | [ ] |
| P185-4 | Guild: smoke triple combo buckets — highest total wins | [ ] |
| P185-1 | Search: Escape clears field `aria-activedescendant` when chips visible | [x] |
| P185-2 | Channels: mixed text+forum category label counts | [x] |
| P185-3 | Notifications: mark-all status `role="status"` dedicated smoke | [x] |
| P185-4 | Guild: smoke triple combo buckets — highest total wins | [x] |
**Next:** Field Escape clear · text+forum label · status role smoke · triple combo buckets.
**Next:** ~~Field Escape clear · text+forum label · status role smoke · triple combo buckets~~ (Phase 185).
---
### Phase 186 — Inbox & guild depth (planned)
| ID | Item | Status |
|----|------|--------|
| P186-1 | Search: field Escape then filter Escape restores chip roving | [ ] |
| P186-2 | Channels: mixed text+announcement category label counts | [ ] |
| P186-3 | Notifications: mark-all status `aria-labelledby` dedicated smoke | [ ] |
| P186-4 | Guild: smoke plain bucket beats lower combo when plain total higher | [ ] |
**Next:** Escape order · text+announcement label · status labelledby smoke · plain over combo.
---
@@ -2388,6 +2401,7 @@ When completing work, change `[ ]` → `[x]` and add a one-line note under **Cha
### Changelog
- **2026-05-22** — v0.8.150: Phase 185 — Field Escape clear, text+forum label, status role create smoke, triple combo buckets (`test:search-recent-chip-field-escape`, `test:channel-category-text-forum-label`, `test:notif-mark-all-status-role-create`, `test:guild-triple-combo-bucket-pick`). Phase 186 planned.
- **2026-05-22** — v0.8.149: Phase 184 — Field Page keys, text+thread label, status aria-label smoke, combo minPos tie (`test:search-recent-chip-field-page`, `test:channel-category-text-thread-label`, `test:notif-mark-all-status-aria-label`, `test:guild-combo-bucket-minpos-tie`). Phase 185 planned.
- **2026-05-22** — v0.8.148: Phase 183 — Field Home/End, thread label, status aria-relevant smoke, combo beats plain equal (`test:search-recent-chip-field-home-end`, `test:channel-category-thread-label`, `test:notif-mark-all-status-aria-relevant`, `test:guild-combo-beats-plain-equal`). Phase 184 planned.
- **2026-05-22** — v0.8.147: Phase 182 — Field activedescendant, text label, status aria-atomic smoke, dual combo buckets (`test:search-recent-chip-field-activedescendant`, `test:channel-category-text-label`, `test:notif-mark-all-status-aria-atomic`, `test:guild-dual-combo-bucket-pick`). Phase 183 planned.
+1 -1
View File
@@ -2,7 +2,7 @@
Documentation for **[Pearcord](https://git.ssh.surf/pearcord)** — a 100% peer-to-peer community chat app on [Pear](https://pear.holepunch.to). No central message servers.
**Current release:** v0.8.149 (desktop app `apps/pearcord`).
**Current release:** v0.8.150 (desktop app `apps/pearcord`).
---
+2
View File
@@ -56,6 +56,8 @@ See also [FORUM_ARCHIVE_SEARCH.md](./FORUM_ARCHIVE_SEARCH.md).
**v0.8.115:** Guild-scoped recent queries persist in `userPrefs.searchRecentByGuild[guildId]` (max 8, deduped). `setSearch` records queries ≥2 chars. Desktop shows **recent chips** under the search input when scope is `guild` and the field is empty. Smokes: `npm run test:search-recent-prefs`, `npm run test:members-online-sort` (UI wiring).
**v0.8.150:** **Escape** on `#channel-search` clears field `aria-activedescendant` when recent chips are visible (filter Escape still runs afterward). Smoke: `npm run test:search-recent-chip-field-escape`.
**v0.8.149:** **Page Up** and **Page Down** from `#channel-search` step the field `aria-activedescendant` by two chips (focus stays in the combobox). Smoke: `npm run test:search-recent-chip-field-page`.
**v0.8.148:** **Home** and **End** from `#channel-search` jump the field `aria-activedescendant` to the first or last recent chip without leaving the combobox. Smoke: `npm run test:search-recent-chip-field-home-end`.