docs: Phase 174 v0.8.139 roadmap, parity, and feature specs
Mark Phase 174 complete and plan Phase 175. Refresh SEARCH, CHANNEL_CATEGORIES, NOTIFICATIONS, IPC, AUTOMATED_TESTING, and parity for Home/End reveal, category label unread, dismiss describedby, and mention-over-root guild pick. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Pearcord architecture
|
||||
|
||||
**Current release:** v0.8.138 (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.139 (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.
|
||||
|
||||
|
||||
@@ -417,7 +417,11 @@ Pearcord validates itself without manual QA.
|
||||
| `npm run test:channel-category-title-describedby` | Category title describedby (`CHANNEL_CATEGORY_TITLE_DESCRIBEDBY_SMOKE_OK`) |
|
||||
| `npm run test:notif-mark-all-describedby` | Mark-all describedby (`NOTIF_MARK_ALL_DESCRIBEDBY_SMOKE_OK`) |
|
||||
| `npm run test:guild-mixed-bucket-pick` | Mixed bucket pick (`GUILD_MIXED_BUCKET_PICK_SMOKE_OK`) |
|
||||
| `npm run test:boot` | `pear run` pre-run (`BOOT_OK`) then Phase 124–173 smokes + `test:companion-boot` |
|
||||
| `npm run test:search-recent-chip-home-end-reveal` | Home/End reveal chips (`SEARCH_RECENT_CHIP_HOME_END_REVEAL_SMOKE_OK`) |
|
||||
| `npm run test:channel-category-label-unread` | Category label unread (`CHANNEL_CATEGORY_LABEL_UNREAD_SMOKE_OK`) |
|
||||
| `npm run test:notif-mark-all-dismiss-describedby` | Dismiss clears describedby (`NOTIF_MARK_ALL_DISMISS_DESCRIBEDBY_SMOKE_OK`) |
|
||||
| `npm run test:guild-mention-root-bucket-pick` | Mention root bucket (`GUILD_MENTION_ROOT_BUCKET_PICK_SMOKE_OK`) |
|
||||
| `npm run test:boot` | `pear run` pre-run (`BOOT_OK`) then Phase 124–174 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`) |
|
||||
|
||||
@@ -23,6 +23,7 @@ Gossip: existing `RPC.CHANNEL_CREATE` carries full channel row including `parent
|
||||
|
||||
## UI
|
||||
|
||||
- Category `aria-label` includes unread and mention totals when present (v0.8.139). Smoke: `npm run test:channel-category-label-unread`.
|
||||
- Category `aria-describedby` pairs `category-title-{id}` with the hidden stats span (v0.8.138). Smoke: `npm run test:channel-category-title-describedby`.
|
||||
- Collapsed and expanded categories: `aria-describedby` includes total unread and mention counts (v0.8.137). Smokes: `npm run test:channel-category-unread-describedby`, `npm run test:channel-category-collapsed-unread-describedby`.
|
||||
- Expanded categories: `aria-describedby` includes total unread and mention counts for child channels (v0.8.136). Smoke: `npm run test:channel-category-unread-describedby`.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Pearcord documentation index
|
||||
|
||||
All project documentation lives in **`pearcord-docs`** (`/Users/raven/dev/pearcord/docs/`). **Release:** v0.8.138.
|
||||
All project documentation lives in **`pearcord-docs`** (`/Users/raven/dev/pearcord/docs/`). **Release:** v0.8.139.
|
||||
|
||||
| Start here | Document |
|
||||
|------------|----------|
|
||||
|
||||
@@ -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.138):
|
||||
When a guild opens, `pearcord-platform` `_selectGuildChannelWithUnread` chooses the active text/forum/thread/announcement channel in this order (v0.8.139):
|
||||
|
||||
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-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-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 |
|
||||
|
||||
@@ -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`
|
||||
- **Dismiss clears describedby (v0.8.139)** — removing the mark-all status banner clears `aria-describedby` on the header button. Smoke: `npm run test:notif-mark-all-dismiss-describedby`
|
||||
- **Mark-all describedby (v0.8.138)** — after mark-all, header button sets `aria-describedby="notif-mark-all-status"` on the status banner. Smoke: `npm run test:notif-mark-all-describedby`
|
||||
- **Mark-all disabled label (v0.8.137)** — disabled header button sets `aria-label="Mark all read, all caught up"`; restored when unread returns. Smoke: `npm run test:notif-mark-all-btn-aria-label`
|
||||
- **Mark-all full a11y (v0.8.136)** — mark-all banner smoke asserts `role`, `aria-live`, `aria-atomic`, `aria-relevant`, and `aria-label`. Smoke: `npm run test:notif-mark-all-status-full-a11y`
|
||||
|
||||
+13
-4
@@ -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.139)
|
||||
|
||||
| Area | Reference product | Pearcord | Gap |
|
||||
|------|-------------------|----------|-----|
|
||||
| Search | Recent queries | Filtered nav + Home/End/arrow keys | Delete reveal (P175); no cloud |
|
||||
| Channels | Categories | Label + describedby unread summary | Collapsed label unread (P175) |
|
||||
| Notifications | Inbox | Mark-all describedby + dismiss cleanup | Restore describedby smoke (P175) |
|
||||
| Guild open | Channel pick | Mention bucket over plain root | Root mention vs category (P175) |
|
||||
|
||||
## Summary (v0.8.138)
|
||||
|
||||
| Area | Reference product | Pearcord | Gap |
|
||||
|------|-------------------|----------|-----|
|
||||
| Search | Recent queries | Filtered nav + arrow/apply keys | Home/End reveal (P174); no cloud |
|
||||
| Channels | Categories | Title + stats describedby | Category label unread (P174) |
|
||||
| Notifications | Inbox | Mark-all label + describedby status | Status dismiss cleanup (P174) |
|
||||
| Guild open | Channel pick | Mixed parent buckets | Mention bucket over root (P174) |
|
||||
| Search | Recent queries | Filtered nav + arrow/apply keys | Home/End reveal (done P174); no cloud |
|
||||
| Channels | Categories | Title + stats describedby | Category label unread (done P174) |
|
||||
| Notifications | Inbox | Mark-all label + describedby status | Status dismiss cleanup (done P174) |
|
||||
| Guild open | Channel pick | Mixed parent buckets | Mention bucket over root (done P174) |
|
||||
|
||||
## Summary (v0.8.137)
|
||||
|
||||
|
||||
+20
-6
@@ -803,16 +803,29 @@ When completing work, change `[ ]` → `[x]` and add a one-line note under **Cha
|
||||
|
||||
---
|
||||
|
||||
### Phase 174 — Inbox & guild depth (planned)
|
||||
### Phase 174 — Inbox & guild depth (v0.8.139)
|
||||
|
||||
| ID | Item | Status |
|
||||
|----|------|--------|
|
||||
| P174-1 | Search: Home/End with filter reveal all before jump | [ ] |
|
||||
| P174-2 | Channels: category `aria-label` includes unread summary | [ ] |
|
||||
| P174-3 | Notifications: dismiss status clears mark-all `aria-describedby` | [ ] |
|
||||
| P174-4 | Guild: smoke higher mention bucket beats plain root bucket | [ ] |
|
||||
| P174-1 | Search: Home/End with filter reveal all before jump | [x] |
|
||||
| P174-2 | Channels: category `aria-label` includes unread summary | [x] |
|
||||
| P174-3 | Notifications: dismiss status clears mark-all `aria-describedby` | [x] |
|
||||
| P174-4 | Guild: smoke higher mention bucket beats plain root bucket | [x] |
|
||||
|
||||
**Next:** Filtered Home/End reveal · category label unread · status dismiss · mention bucket smoke.
|
||||
**Next:** ~~Filtered Home/End reveal · category label unread · status dismiss · mention root bucket smoke~~ (Phase 174).
|
||||
|
||||
---
|
||||
|
||||
### Phase 175 — Search & guild polish (planned)
|
||||
|
||||
| ID | Item | Status |
|
||||
|----|------|--------|
|
||||
| P175-1 | Search: Delete with filter reveals all before removing chip | [ ] |
|
||||
| P175-2 | Channels: collapsed category `aria-label` unread summary | [ ] |
|
||||
| P175-3 | Notifications: mark-all restore clears stale `aria-describedby` smoke | [ ] |
|
||||
| P175-4 | Guild: smoke mention in root beats higher plain in category | [ ] |
|
||||
|
||||
**Next:** Filtered Delete reveal · collapsed label unread · restore describedby · root mention smoke.
|
||||
|
||||
---
|
||||
|
||||
@@ -2245,6 +2258,7 @@ When completing work, change `[ ]` → `[x]` and add a one-line note under **Cha
|
||||
|
||||
### Changelog
|
||||
|
||||
- **2026-05-22** — v0.8.139: Phase 174 — Home/End reveal filtered chips, category label unread, dismiss clears describedby, mention root bucket (`test:search-recent-chip-home-end-reveal`, `test:channel-category-label-unread`, `test:notif-mark-all-dismiss-describedby`, `test:guild-mention-root-bucket-pick`). Phase 175 planned.
|
||||
- **2026-05-22** — v0.8.138: Phase 173 — Arrow reveals filtered chips, category title describedby, mark-all describedby status, mixed bucket pick (`test:search-recent-chip-arrow-reveal`, `test:channel-category-title-describedby`, `test:notif-mark-all-describedby`, `test:guild-mixed-bucket-pick`). Phase 174 planned.
|
||||
- **2026-05-22** — v0.8.137: Phase 172 — Enter applies filtered chip, collapsed unread describedby, mark-all disabled label, dual-category isolation (`test:search-recent-chip-enter-apply`, `test:channel-category-collapsed-unread-describedby`, `test:notif-mark-all-btn-aria-label`, `test:guild-dual-category-isolation-pick`). Phase 173 planned.
|
||||
- **2026-05-22** — v0.8.136: Phase 171 — Space applies filtered chip, category unread describedby, mark-all full a11y smoke, mention single-category pick (`test:search-recent-chip-space-apply`, `test:channel-category-unread-describedby`, `test:notif-mark-all-status-full-a11y`, `test:guild-mention-single-category-pick`). Phase 172 planned.
|
||||
|
||||
@@ -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.138 (desktop app `apps/pearcord`).
|
||||
**Current release:** v0.8.139 (desktop app `apps/pearcord`).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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.139:** **Home** and **End** in the recent-chip listbox clear an active filter before jumping to the first or last chip. Smoke: `npm run test:search-recent-chip-home-end-reveal`.
|
||||
|
||||
**v0.8.138:** **Arrow** keys in the recent-chip listbox clear an active filter before moving roving focus. Smoke: `npm run test:search-recent-chip-arrow-reveal`.
|
||||
|
||||
**v0.8.137:** **Enter** with an active chip filter clears the filter and applies the focused chip (or first visible from the field). Smoke: `npm run test:search-recent-chip-enter-apply`.
|
||||
|
||||
Reference in New Issue
Block a user