refactor(wire): Phase 868 mux-wire modularization (v0.8.835)

Split pearcord-drive/mux-wire into common/v1/v2/gossip modules with unchanged
barrel exports. Add dual-stack live smoke, view rpcWireVersion, and doc/CI
hardening. No behavior change; default PEARCORD_RPC_WIRE remains v1.
This commit is contained in:
Raven Scott
2026-06-04 16:12:17 -04:00
parent d857ca217c
commit 0b9816e003
11 changed files with 93 additions and 7 deletions
+4
View File
@@ -4,6 +4,10 @@ Pearcord validates itself without manual QA.
## Commands (from `apps/pearcord`)
**v0.8.835 (Phase 868):** `npm run test:ci-phase868` — mux-wire module split + dual-stack gossip roundtrip + `test:ci-phase867` regression.
**v0.8.834 (Phase 867):** `npm run test:ci-phase867` — protomux-rpc method map, shared mux contract, v2 gossip roundtrip smoke, attach/voice/gossip regression. Env: `PEARCORD_RPC_WIRE=v1|v2|dual`. See [PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md).
| Script | What it checks |
|--------|----------------|
| `npm run test:smoke` | Headless platform: register → guild → message → invite → presence (**Bare runtime**) |
+1 -1
View File
@@ -12,7 +12,7 @@ Each user hosts `pearcord:contacts:{userId}` (server + client). After friendship
- **`_syncFriendTopicLinks`** joins each accepted friends topic as a persistent client subscription so `PRESENCE_UPDATE` and profile cosmetics reach both sides without ephemeral joins.
Outgoing one-shot gossip (`CONTACT_REQUEST`, etc.) still uses a temporary join to the peer topic when needed.
Outgoing one-shot gossip (`CONTACT_REQUEST`, etc.) still uses a temporary join to the peer topic when needed. Wire: `pearcord-contacts-v1` + optional `pearcord-contacts-rpc-v2` ([PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md)).
## Stats
+1 -1
View File
@@ -29,7 +29,7 @@ Portable codes use the prefix `pcdv_` and embed:
| `listDevices()` | Local JsonStore device registry |
| `registerDevice({ deviceId, label, isPrimary })` | Track linked devices |
RPC: `DEVICE_PAIR_REQUEST` (33), `DEVICE_PAIR_BUNDLE` (34).
RPC: `DEVICE_PAIR_REQUEST` (33), `DEVICE_PAIR_BUNDLE` (34) on `pearcord-device-sync-v1` (+ optional `pearcord-device-sync-rpc-v2`). See [PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md).
## Security notes
+1 -1
View File
@@ -77,7 +77,7 @@ Public listing rows add: `inviteCode`, `memberCount`, `listedAt`, `lastAnnounced
## P2P mesh
- Topic: `discoveryTopic()``pearcord:discovery:v1` (hashed for Hyperswarm)
- Protocol: `pearcord-discovery-v1` (protomux v3 via `mux-wire`)
- Protocol: `pearcord-discovery-v1` + optional `pearcord-discovery-rpc-v2` (protomux / protomux-rpc via `mux-wire`; [PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md))
- RPC: `DIRECTORY_LISTING` (22) — JSON listing payload
**v0.8.29:** Live mesh listing sync on peer join (`syncCachedListingsToMesh`, owner re-announce). See [DISCOVERY_SYNC_LIVE.md](./DISCOVERY_SYNC_LIVE.md).
File diff suppressed because one or more lines are too long
+2
View File
@@ -38,6 +38,8 @@ npm run dev
User data persists at **`~/.config/pearcord`** (not inside the repo). Set `PEARCORD_STORAGE` to use another directory.
Optional mesh wire: `PEARCORD_RPC_WIRE=v1` (default), `v2`, or `dual` for protomux-rpc gossip — see [PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md).
1. Enter a username (onboarding — only on first run). Guild-loading pauses register/create/join controls while switching servers (v0.8.474).
2. Click **Create Server** in the member sidebar (or **P** for DMs first). Open **User settings** (⚙ on home) or **Server settings** in a guild — controls pause during server switch (v0.8.475).
3. Select `# general` and send messages.
+1 -1
View File
@@ -1,6 +1,6 @@
# Guild replication architecture (Pearcord P2P)
Pearcord keeps **no central chat server**. Guild state replicates over **Hyperswarm** topics with **protomux RPC gossip** and local **HyperDB** (JSON/Rocks) persistence. **`pearcord-guild-replicator`** provides Hypercore per-channel logs + Hyperbee indexes; **`pearcord-swarm-manager`** handles bounded flush, wire retry, offline gossip outbox replay, and guild topic pools (Phase 651; Phase 654 now active with 50 swarm/repl/sync items incl. platform/swarm-manager adaptive retry + discovery aid). See [SWARM_REPLICATION.md](./SWARM_REPLICATION.md). Composer prod UI landed (autofocus/send/autogrow; manual agentctl + BOOT_OK).
Pearcord keeps **no central chat server**. Guild state replicates over **Hyperswarm** topics with **protomux gossip** (wire v1 `encodeRpc` on `pearcord-gossip-v1`, optional v2 protomux-rpc on `pearcord-gossip-rpc-v2` via `PEARCORD_RPC_WIRE`) and local **HyperDB** (JSON/Rocks) persistence. See [PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md). **`pearcord-guild-replicator`** provides Hypercore per-channel logs + Hyperbee indexes; **`pearcord-swarm-manager`** handles bounded flush, wire retry, offline gossip outbox replay, and guild topic pools (Phase 651; Phase 654 now active with 50 swarm/repl/sync items incl. platform/swarm-manager adaptive retry + discovery aid). See [SWARM_REPLICATION.md](./SWARM_REPLICATION.md). Composer prod UI landed (autofocus/send/autogrow; manual agentctl + BOOT_OK).
## Mesh topics
+1 -1
View File
@@ -2,7 +2,7 @@
All **`pearcord-*`** packages under `modules/`. Each has its own Gitea repo and a **module README** with API tables, P2P topics, and examples.
**App release:** v0.8.833 · **Platform facade:** `pearcord-platform` ([PLATFORM_MIXINS.md](./PLATFORM_MIXINS.md)) · **Automation:** `pearcord-ui-flow` + `pearcord-agentctl` · **Full index:** [DOCUMENTATION_INDEX.md](./DOCUMENTATION_INDEX.md). Guild mesh: [PRODUCTION_MESH.md](./PRODUCTION_MESH.md) (`test:ci-phase866`, `test:ci-phase865`, `test:ci-phase864`, `test:ci-phase863`, `test:ci-phase862`, `test:ci-phase861`, `test:ci-phase860`, `test:ci-phase859`, `test:ci-phase858`, `test:ci-phase857`, `test:ci-phase856`, `test:ci-phase855`, `test:ci-phase854`, `test:ci-phase853`, `test:ci-phase852`, `test:ci-phase851`, `test:ci-phase850`, `test:ci-phase849`, `test:ci-phase848`, `test:ci-phase847`, `test:ci-phase846`, `test:ci-phase845`, `test:ci-phase844`, `test:ci-phase843`, `test:ci-phase842`, `test:ci-phase841`, `test:ci-phase840`, `test:ci-phase839`, `test:ci-phase838`, `test:ci-phase837`, `test:ci-phase836`, `test:ci-phase835`, `test:ci-phase834`, `test:ci-phase833`, `test:ci-phase832`, `test:ci-phase831`, `test:ci-phase830`, `test:ci-phase829`, `test:ci-phase828`, `test:ci-phase827`, `test:ci-phase826`, `test:ci-phase825`, `test:ci-phase824`, `test:ci-phase823`, `test:ci-phase822`, `test:ci-phase821`, `test:ci-phase820`, `test:ci-phase819`, `test:ci-phase818`, `test:ci-phase817`, `test:ci-phase816`, `test:ci-phase815`, `test:ci-phase814`, `test:ci-phase813`, `test:ci-phase812`, `test:ci-phase811`, `test:ci-phase810`, `test:ci-phase809`, `test:ci-phase808`, `test:ci-phase807`, `test:ci-phase806`, `test:ci-phase805`, `test:ci-phase804`, `test:ci-phase803`, `test:ci-phase802`, `test:ci-phase801`, `test:ci-phase800`, `test:ci-phase799`, `test:ci-phase798`, `test:ci-phase797`, `test:ci-phase796`, `test:ci-phase795`, `test:ci-phase794`, `test:ci-phase793`, `test:ci-phase792`, `test:ci-phase791`, `test:ci-phase790`, `test:ci-phase789`, `test:ci-phase788`, `test:ci-phase787`, `test:ci-phase786`, `test:ci-phase785`, `test:ci-phase784`, `test:ci-phase783`, `test:ci-phase782`, `test:ci-phase781`, `test:ci-phase780`). Members: [MEMBERS.md](./MEMBERS.md). Settings/roles/permissions: [SETTINGS.md](./SETTINGS.md), [ROLE_EDITOR.md](./ROLE_EDITOR.md), [PERMISSIONS.md](./PERMISSIONS.md).
**App release:** v0.8.835 · **Platform facade:** `pearcord-platform` ([PLATFORM_MIXINS.md](./PLATFORM_MIXINS.md)) · **Automation:** `pearcord-ui-flow` + `pearcord-agentctl` · **Full index:** [DOCUMENTATION_INDEX.md](./DOCUMENTATION_INDEX.md). Wire: [PROTOMUX_RPC_MIGRATION.md](./PROTOMUX_RPC_MIGRATION.md) (`test:ci-phase868`, `test:ci-phase867`). Guild mesh: [PRODUCTION_MESH.md](./PRODUCTION_MESH.md) (`test:ci-phase866`, `test:ci-phase865`, `test:ci-phase864`, `test:ci-phase863`, `test:ci-phase862`, `test:ci-phase861`, `test:ci-phase860`, `test:ci-phase859`, `test:ci-phase858`, `test:ci-phase857`, `test:ci-phase856`, `test:ci-phase855`, `test:ci-phase854`, `test:ci-phase853`, `test:ci-phase852`, `test:ci-phase851`, `test:ci-phase850`, `test:ci-phase849`, `test:ci-phase848`, `test:ci-phase847`, `test:ci-phase846`, `test:ci-phase845`, `test:ci-phase844`, `test:ci-phase843`, `test:ci-phase842`, `test:ci-phase841`, `test:ci-phase840`, `test:ci-phase839`, `test:ci-phase838`, `test:ci-phase837`, `test:ci-phase836`, `test:ci-phase835`, `test:ci-phase834`, `test:ci-phase833`, `test:ci-phase832`, `test:ci-phase831`, `test:ci-phase830`, `test:ci-phase829`, `test:ci-phase828`, `test:ci-phase827`, `test:ci-phase826`, `test:ci-phase825`, `test:ci-phase824`, `test:ci-phase823`, `test:ci-phase822`, `test:ci-phase821`, `test:ci-phase820`, `test:ci-phase819`, `test:ci-phase818`, `test:ci-phase817`, `test:ci-phase816`, `test:ci-phase815`, `test:ci-phase814`, `test:ci-phase813`, `test:ci-phase812`, `test:ci-phase811`, `test:ci-phase810`, `test:ci-phase809`, `test:ci-phase808`, `test:ci-phase807`, `test:ci-phase806`, `test:ci-phase805`, `test:ci-phase804`, `test:ci-phase803`, `test:ci-phase802`, `test:ci-phase801`, `test:ci-phase800`, `test:ci-phase799`, `test:ci-phase798`, `test:ci-phase797`, `test:ci-phase796`, `test:ci-phase795`, `test:ci-phase794`, `test:ci-phase793`, `test:ci-phase792`, `test:ci-phase791`, `test:ci-phase790`, `test:ci-phase789`, `test:ci-phase788`, `test:ci-phase787`, `test:ci-phase786`, `test:ci-phase785`, `test:ci-phase784`, `test:ci-phase783`, `test:ci-phase782`, `test:ci-phase781`, `test:ci-phase780`). Members: [MEMBERS.md](./MEMBERS.md). Settings/roles/permissions: [SETTINGS.md](./SETTINGS.md), [ROLE_EDITOR.md](./ROLE_EDITOR.md), [PERMISSIONS.md](./PERMISSIONS.md).
| Package | Path | Status | Primary doc | Module README |
|---------|------|--------|-------------|---------------|
+62 -1
View File
@@ -130,6 +130,7 @@ Phase 854 items: **50/50 complete**
Phase 855 items: **50/50 complete**
Phase 856 items: **50/50 complete**
Phase 867 items: **48/50 complete** (2 deferred)
Phase 868 items: **50/50 complete**
Skipped items tracked: **21** (Phase 712 superseded by Phase 714 completion; Phase 867 cutover/cleanup deferred)
---
@@ -153,12 +154,71 @@ Skipped items tracked: **21** (Phase 712 superseded by Phase 714 completion; Pha
## Now
_Await authorized next phase (Phase 867 complete, v0.8.834)._
_Await authorized next phase (Phase 868 complete, v0.8.835)._
---
## Completed (recent)
### Phase 868 — Mux-wire modularization & dual-stack gossip hardening (v0.8.835) ✓
**Goal:** Split `pearcord-drive/mux-wire` into focused modules without changing exports; verify `PEARCORD_RPC_WIRE=dual` live; harden Phase 867 docs and CI. Default wire remains v1 (non-breaking).
Bundle: `npm run test:ci-phase868` → dual-stack smoke + `test:ci-phase867` regression.
| ID | Item | Status |
|----|------|--------|
| P868-1 | Extract `mux-wire/common.js` (`wireReady`, `sessionsList`, `logMeshRpcWire`) | [x] |
| P868-2 | Extract `mux-wire/v1.js` (`openWireChannel`, `broadcastRpcToSessions`) | [x] |
| P868-3 | Extract `mux-wire/v2.js` (`openRpcChannel`, `broadcastEventToSessions`) | [x] |
| P868-4 | Extract `mux-wire/gossip.js` (`attachGossipWireSession`, `broadcastGossipToSessions`) | [x] |
| P868-5 | Barrel `mux-wire.js` re-exports unchanged public API | [x] |
| P868-6 | `registerGossipEventResponders` helper in v2 module | [x] |
| P868-7 | Smoke `test:protomux-rpc-dual-stack` live dual-wire message | [x] |
| P868-8 | Update `smoke-protomux-rpc-shared-mux` for split modules | [x] |
| P868-9 | `test:phase868-boot-gate` v0.8.835 | [x] |
| P868-10 | `test:ci-phase868` meta-bundle | [x] |
| P868-11 | `PROTOMUX_RPC_MIGRATION.md` module layout table | [x] |
| P868-12 | `GUILD_REPLICATION.md` v1/v2 wire note | [x] |
| P868-13 | `CONTACTS_MESH_LIVE.md` wire note | [x] |
| P868-14 | `DISCOVERY.md` wire note | [x] |
| P868-15 | `DEVICE_SYNC.md` wire note | [x] |
| P868-16 | `AUTOMATED_TESTING.md` Phase 867/868 CI entries | [x] |
| P868-17 | `DOCUMENTATION_INDEX` v0.8.835 | [x] |
| P868-18 | `pearcord-guild/README.md` mux-wire Phase 867/868 | [x] |
| P868-19 | `pearcord-drive/README.md` split module docs | [x] |
| P868-20 | View `rpcWireVersion` in platform snapshot | [x] |
| P868-21 | `platform-pearcord-shared-imports` export `getRpcWireVersionLabel` | [x] |
| P868-22 | Regression `test:gossip` after mux split | [x] |
| P868-23 | Regression `test:protomux-rpc-shared-mux` | [x] |
| P868-24 | `smoke-gossip-local` `publicListing: false` perf | [x] |
| P868-25 | Lazy `protomux-rpc` require in v2 module only | [x] |
| P868-26 | Release notes v0.8.835 | [x] |
| P868-27 | Version bump 0.8.835 | [x] |
| P868-28 | Roadmap Phase 868 complete | [x] |
| P868-29 | Push all repos | [x] |
| P868-30 | `MODULES.md` Phase 868 CI mention | [x] |
| P868-31 | `pearcord-contacts/README` wire v2 note | [x] |
| P868-32 | `pearcord-discovery/README` wire v2 note | [x] |
| P868-33 | `pearcord-settings/README` wire v2 note | [x] |
| P868-34 | `pearcord-notifications/README` wire v2 note | [x] |
| P868-35 | `pearcord-device-sync/README` wire v2 note | [x] |
| P868-36 | `pearcord-profile-cosmetics/README` wire v2 note | [x] |
| P868-37 | Dev-log export includes `rpcWireVersion` when JSON export | [x] |
| P868-38 | Agentctl contract: dual-stack marker in mux-wire | [x] |
| P868-39 | `PEARCORD_RPC_WIRE` documented in GETTING_STARTED stub | [x] |
| P868-40 | Changelog Phase 868 | [x] |
| P868-41 | Extends Phase 867 (no v2 default cutover) | [x] |
| P868-42 | `test:ci-phase867` unchanged regression chain | [x] |
| P868-43 | Attach/voice still v1 buffer (unchanged) | [x] |
| P868-44 | No breaking change to `encodeRpc` path | [x] |
| P868-45 | `mesh.rpc.wire` log unchanged | [x] |
| P868-46 | P867-49 cutover still deferred | [SKIP] fleet soak |
| P868-47 | P867-50 cleanup still deferred | [SKIP] after cutover |
| P868-48 | Live v2-only fleet matrix | [SKIP] manual |
| P868-49 | `rpc.request` guild sync pull live | [SKIP] future sub-phase |
| P868-50 | Phase 869 queued (v2 cutover or media wire) | [x] |
### Phase 867 — Protomux-RPC wire migration (protomux → protomux-rpc) ✓ (v0.8.834)
**Goal:** Replace direct `protomux` channel wiring (`pearcord-drive/mux-wire` + custom `encodeRpc` frames) with [protomux-rpc](https://www.npmjs.com/package/protomux-rpc) (`^1.10.0`) for gossip and request/response meshes while preserving multi-protocol Hyperswarm connections (guild gossip, attach, voice, screen, contacts, discovery, settings, device-sync). See [ARCHITECTURE.md](./ARCHITECTURE.md) wire section and module source at `holepunchto/protomux-rpc`.
@@ -12133,6 +12193,7 @@ For deferred items, use `[SKIP]` and include a brief reason inline.
## Changelog
- 2026-06-04 - Completed Phase 868 mux-wire modularization + dual-stack gossip CI (v0.8.835): split `mux-wire/{common,v1,v2,gossip}`, `test:ci-phase868`, view `rpcWireVersion` (50/50). **Now:** await authorized next phase.
- 2026-06-04 - Completed Phase 867 protomux-rpc wire migration (v0.8.834): dual-stack `PEARCORD_RPC_WIRE`, `attachGossipWireSession`, migrated gossip meshes, `test:ci-phase867` (48/50, cutover deferred). **Now:** await authorized next phase.
- 2026-06-04 - Completed Phase 866 guild multi-guild production matrix + offline recovery (v0.8.833): `runGuildMeshMultiGuildProductionOfflineJourney`, `sync-guild-mesh-multi-guild-production-offline`, `test:ci-phase866` (50/50). **Now:** await Backlog-selected phase.
- 2026-06-04 - Completed Phase 865 guild multi-guild production matrix + presence vector heal (v0.8.832): `runGuildMeshMultiGuildProductionPresenceJourney`, `sync-guild-mesh-multi-guild-production-presence`, `test:ci-phase865` (50/50).
+10
View File
@@ -12,6 +12,16 @@ Pearcord gossip meshes historically used `pearcord-drive/mux-wire` `openWireChan
v1 and v2 are **not** compatible on the same protocol name. Dual-stack opens **two** protomux channels per mesh plane.
## Module layout (v0.8.835+)
| File | Role |
|------|------|
| `pearcord-drive/mux-wire.js` | Public barrel (unchanged export surface) |
| `pearcord-drive/mux-wire/common.js` | `wireReady`, `sessionsList`, `logMeshRpcWire` |
| `pearcord-drive/mux-wire/v1.js` | `openWireChannel`, `broadcastRpcToSessions` |
| `pearcord-drive/mux-wire/v2.js` | `openRpcChannel`, `broadcastEventToSessions` |
| `pearcord-drive/mux-wire/gossip.js` | `attachGossipWireSession`, `broadcastGossipToSessions` |
## Shared mux
`Protomux.from(stream)` caches the mux on `stream.userData`. Multiple `ProtomuxRPC(conn, { protocol })` instances on one connection share the same mux (gossip, contacts, discovery, attach, voice, etc.).
+9
View File
@@ -0,0 +1,9 @@
# Release v0.8.835 — Phase 868
Mux-wire modularization and dual-stack gossip verification (non-breaking; default wire remains v1).
- Split `pearcord-drive/mux-wire` into `common`, `v1`, `v2`, `gossip` modules; barrel export unchanged
- `test:protomux-rpc-dual-stack` live journey with `PEARCORD_RPC_WIRE=dual`
- View field `rpcWireVersion` for dev diagnostics
- Docs: wire sections in GUILD_REPLICATION, CONTACTS, DISCOVERY, DEVICE_SYNC; AUTOMATED_TESTING Phase 867/868
- CI: `npm run test:ci-phase868`