@sym-bot/mesh-channel 0.3.11 → 0.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,587 +1,627 @@
1
- # Changelog
2
-
3
- ## 0.3.7
4
-
5
- ### Changed
6
-
7
- - **Bumped `@sym-bot/sym` dependency `^0.5.8` `^0.7.4`** to track the current sym stack. The range had drifted: sym moved through 0.6.x/0.7.x (mesh groups, Windows portability) while this wrapper still declared `^0.5.8`, so an installed sym ≥0.6 showed as `invalid` and a reinstall could nest a stale 0.5.x that shadows the global. Pinning `^0.7.4` makes the dependency honest and, in particular, **requires the loopback-capable sym (≥0.7.4)** co-resident nodes mesh over `127.0.0.1` with no network interface (Wi-Fi off). No code change in this package; dependency-range correctness only.
8
-
9
- ## 0.3.6
10
-
11
- ### Added
12
-
13
- - **Group discovery beacon.** This MCP node now advertises its mesh group on a shared `_symgroups._tcp` service (group name in TXT) via the pure-JS `bonjour-service` — published on start, re-published on `sym_join_group` hot-swap, torn down on shutdown. Makes the Claude/MCP node discoverable by the `sym` CLI's `sym groups` command **cross-platform, including Windows** (where Apple's `dns-sd` is absent), so CLI-daemon and Claude/MCP nodes list together. Discovery-only — comms stay isolated on the group's own `_<group>._tcp`. `bonjour-service` pinned as a direct dependency. Validated on Windows 11.
14
- - **Operational note:** a session started before 0.3.6 must restart to begin beaconing.
15
-
16
- ## 0.3.5
17
-
18
- ### Added
19
-
20
- - **Opaque payload on `sym_send` / `sym_observe`.** Both tools accept
21
- an optional `payload` argument carrying data beyond CAT7 — any
22
- JSON-serializable value. Forwarded to `SymNode.remember(fields, {
23
- payload, … })` (requires `@sym-bot/sym` ≥ 0.5.8) and rides the wire
24
- frame to peers. Used by substrate-level protocols that need to carry
25
- structured data alongside CAT7 (e.g. LLM request/response, where the
26
- prompt + request_id ride in `payload` rather than getting smuggled
27
- through `motivation`).
28
- - **Channel notifications surface payload-bearing CMBs.** When an
29
- incoming peer CMB carries `cmb.payload`, the header gains a
30
- `[+payload Nb]` indicator and the body stored by `sym_fetch`
31
- includes a `---PAYLOAD---` section with the serialized payload.
32
- Receivers learn from the header that there's structured data beyond
33
- CAT7 and call `sym_fetch` to consume it.
34
- - Base MCP instructions now teach agents to recognise the
35
- `[+payload Nb]` header and to pass structured responses via the
36
- `payload` argument when emitting substrate-level CMBs.
37
-
38
- ### Compatibility
39
-
40
- - Omitting `payload` produces a v0.3.4-shaped CAT7 CMB byte-for-byte.
41
- - Old peers (without `cmb.payload`) surface unchanged headers no
42
- `[+payload …]` indicator, no PAYLOAD section in the body.
43
-
44
- ## 0.3.4
45
-
46
- ### Added
47
-
48
- - **`SYM_GROUP` is now first-class in the installer.** `init` accepts a
49
- `--group <name>` flag and reads the `SYM_GROUP` env var; both paths
50
- persist the chosen group into the `~/.claude.json` (or project
51
- `.mcp.json`) env block so every Claude Code launch auto-joins the
52
- named group instead of the global `_sym._tcp` mesh.
53
-
54
- Resolution order is `--force`-aware:
55
- - With `--force` and an explicit `--group`/`SYM_GROUP`: flag/env wins
56
- (one-command group switch on a live entry).
57
- - Without `--force`, or with `--force` but no explicit value:
58
- preserved value from any existing entry > explicit > none (omit).
59
-
60
- `--force --group default` (or `SYM_GROUP=default`) is the explicit
61
- escape hatch to revert a node from a named group back to the global
62
- mesh removes `SYM_GROUP` from the env block entirely rather than
63
- writing the literal string "default".
64
-
65
- Both `--group` and `SYM_GROUP` env values are validated against the
66
- same kebab-case regex; malformed values exit with a clear error
67
- before any file write.
68
-
69
- - **`doctor` now reports the persisted group per entry** and warns when
70
- user-global and project-scoped entries disagree on `SYM_GROUP`.
71
- Group-mismatch is the most common cause of "peers never appear in
72
- `sym_peers`" with no other failure signal surfacing it inline saves
73
- the diagnostic walk that motivated this release.
74
-
75
- - **README** gains a "Persisting your group across restarts" subsection
76
- under Team mesh groups, plus a troubleshooting entry covering the
77
- group-mismatch failure mode. Quick-start shows the `--group` flag.
78
-
79
- ### Fixed
80
-
81
- - **Stale-entry heal preserves `SYM_GROUP` alongside `SYM_NODE_NAME`.**
82
- Previously, healing a stale `claude-sym-mesh` entry (args[0] points at
83
- a missing server.js) silently dropped any persisted `SYM_GROUP`,
84
- reverting the node to the default mesh on next launch and stranding
85
- teammates who stayed in the named group. The heal path now copies
86
- both fields from the prior entry into the rewrite.
87
-
88
- Same fix applied to project-scoped entry healing under
89
- `claudeJson.projects[<path>].mcpServers`.
90
-
91
- ### Why this matters
92
-
93
- Before 0.3.4, the only way to persist a group was to hand-edit
94
- `~/.claude.json`. The README pitched `sym_join_group` as the team-mesh
95
- UX, but that tool is runtime-only the next Claude Code launch reverted
96
- the node to the default mesh, peer count dropped to zero, and the user
97
- saw no diagnostic signal. The 2026-05-02 SYM.BOT incident (CMO in
98
- `default`, COO in `sym-bot-team`, ~24h of silent duplex outage) traced
99
- directly to this gap.
100
-
101
- ## 0.3.3
102
-
103
- ### Fixed
104
-
105
- - **Real-time duplex for CAT7 CMBs.** The `cmb-accepted` handler now
106
- stores the rendered CMB body under an `[mNNN]` ID and includes that
107
- ID in the channel notification, matching the contract stated in the
108
- MCP instructions ("Messages arrive as compact headers with [mNNN] IDs
109
- use sym_fetch to read the full content") and the behaviour of the
110
- raw-text `message` path.
111
-
112
- Previously only the legacy raw-text `message` event persisted bodies
113
- to `MESSAGE_STORE` the primary `cmb-accepted` event (fired for
114
- every structured CMB delivered via `sym_send` / `sym_observe`) pushed
115
- a headline with no `[mNNN]` and left no retrievable body. Inbound
116
- CMBs were admitted to the SVAF-backed memory store and surfaced by
117
- `sym_recall` as compact headlines, but `sym_fetch` could not return
118
- their content — the duplex was effectively headline-only for the 99%
119
- case of real mesh traffic.
120
-
121
- Symptom: after the 0.3.2 Mac↔Win fix restored bidirectional packet
122
- flow, peers' structured replies appeared in `sym_recall` but returned
123
- *"expired or invalid ID"* from `sym_fetch` because `storeMessage()`
124
- had never been called for them. Now both the raw-text and CAT7 paths
125
- persist bodies identically.
126
-
127
- ## 0.3.2
128
-
129
- ### Fixed
130
-
131
- - **Pulls in `@sym-bot/sym` 0.5.1** — fixes Mac↔Windows peer connections
132
- over LAN. Prior releases shipped a Bonjour advertisement whose SRV
133
- target was the bare Windows NetBIOS hostname (e.g. `xmesh-hp.`) with
134
- no `.local` suffix. macOS mDNSResponder only resolves `.local.` mDNS
135
- names, so Macs could discover Windows peers via bonjour browse but
136
- failed to open the outbound TCP connection. CMBs targeted at Windows
137
- nodes never arrived; no replies came back. Full diagnosis in sym
138
- 0.5.1 CHANGELOG.
139
-
140
- Upgrade required on both sides to restore Mac↔Windows traffic.
141
- Existing Windows identities with a bare hostname are auto-migrated
142
- on next node start; no manual config edit needed.
143
-
144
- ## 0.3.1
145
-
146
- ### Fixed
147
-
148
- - **Installer no longer silently ships a broken MCP config.** Previously,
149
- if `~/.claude.json` already contained a `claude-sym-mesh` entry,
150
- `npm install -g @sym-bot/mesh-channel` (via postinstall) and
151
- `npx @sym-bot/mesh-channel init` both skipped with "already configured"
152
- even when the entry's `args[0]` server.js path no longer existed on
153
- disk (common after moving or reinstalling the repo). Users saw
154
- `/mcp` report "Failed to reconnect" with no diagnostic hint.
155
-
156
- The installer now classifies entries whose `args[0]` is missing as
157
- **stale** and rewrites them automatically without `--force`, preserving
158
- `SYM_NODE_NAME` from the prior entry so mesh identity doesn't drift
159
- back to the hostname-based default. Live entries continue to require
160
- `--force` for overwrite.
161
-
162
- - **Stale project-scoped entries are now healed too.** `~/.claude.json`
163
- can carry per-project `mcpServers` overrides under
164
- `projects.<dir>.mcpServers`, and Claude Code prefers those over the
165
- user-global entry when launched from that directory. A healthy
166
- user-global entry was therefore being silently shadowed by stale
167
- project entries. `init` now scans every project, rewrites any stale
168
- `claude-sym-mesh` entry, and preserves each project's `SYM_NODE_NAME`.
169
-
170
- ### Added
171
-
172
- - **`sym-mesh-channel doctor` subcommand.** Read-only diagnostic that
173
- lists every `claude-sym-mesh` entry in `~/.claude.json` (user-global
174
- and every project scope) with `[live]` or `[STALE]` plus its
175
- `SYM_NODE_NAME` and configured path. Point users here when `/mcp`
176
- reports "Failed to reconnect". No writes, safe to run any time.
177
-
178
- - **README troubleshooting section** covering the `/mcp` failure path,
179
- how to run `doctor`, and when restart is needed after a config change.
180
-
181
- ### Changed
182
-
183
- - `.claude-plugin/plugin.json` version field bumped to `0.3.1` to match
184
- `package.json`. Previous drift (`plugin.json` stuck at `0.2.0`, package
185
- at `0.3.0`) was caught by the in-repo version-parity test.
186
-
187
- ## 0.3.0
188
-
189
- ### Added
190
-
191
- - **Startup remix-memory primer automates agent memory recall on
192
- session/agent restart (MMP §4.2 O2, rejoin-without-replay).** As the
193
- final step of plugin initialisation (after `node.start()` and before
194
- the MCP transport connects), the plugin calls
195
- `node.buildStartupPrimer()` and appends the returned text to the MCP
196
- server's `instructions` field. A fresh Claude Code session wakes
197
- with the agent's own remix memory own observations plus peer
198
- observations admitted by SVAF already loaded into context. No
199
- first-turn `sym_recall` required; agent acts from prior state
200
- immediately.
201
-
202
- Default caps: last 24 hours OR 20 most recent CMBs, whichever is
203
- tighter. The primer lists each entry as `[timestamp] source · key —
204
- focus` and surfaces a dropped-count line when caps elide older
205
- entries. Empty store is a silent no-op.
206
-
207
- ### Changed
208
-
209
- - **`@sym-bot/sym` dep bumped to `^0.5.0`** to pick up the
210
- `buildStartupPrimer` helper and to keep every plugin on the
211
- sym.day platform pinned to the same substrate SDK version
212
- (no drift across mesh-channel / melotune-plugin / future
213
- specialised plugins).
214
-
215
- ## 0.2.0
216
-
217
- ### Breaking
218
-
219
- - **`sym_send` tool signature change.** `sym_send` now emits a structured
220
- CAT7 CMB (MMP §4.2) instead of a raw-text `type:'message'` frame, and
221
- accepts an optional `to` parameter for targeted single-peer delivery
222
- per MMP §4.4.4.
223
-
224
- Old signature: `sym_send(message: string)`
225
- New signature: `sym_send(focus: string (required), issue?, intent?,
226
- motivation?, commitment?, perspective?, mood?, to?)`
227
-
228
- Migration: agents that previously called `sym_send({message: "..."})`
229
- should now pass the CAT7 fields explicitly, with `focus` carrying the
230
- task anchor for the send. Prior ephemeral text-broadcast behaviour is
231
- no longer exposed at the tool surface `sym_send` and `sym_observe`
232
- both emit CMBs now, receivers run SVAF per §9.2, and admitted CMBs are
233
- remix-stored with lineage. The low-level `node.send(text)` SDK API is
234
- unchanged but no longer surfaced as a tool.
235
-
236
- ### Added
237
-
238
- - **Targeted CMB send.** `sym_send` resolves `to` against connected
239
- peers by full nodeId first, then display name, then 8-char prefix.
240
- Ambiguous matches return an error asking for the full nodeId; a
241
- disconnected target returns an error and suggests `sym_peers`.
242
- - **Tool descriptions** for `sym_send` and `sym_observe` now explicitly
243
- call out the SVAF receive path and lineage semantics, and the MCP
244
- server's `instructions` string reflects the new division of labour.
245
- - **`@sym-bot/sym` dependency bumped to `^0.3.81`** for
246
- `remember(fields, {to})` targeted variant and `peers().peerId`.
247
-
248
- ## 0.1.23
249
-
250
- ### Added
251
-
252
- - **`sym_join_group(group, relay_url?, relay_token?)`** hot-swap this
253
- node into a different mesh group at runtime, no Claude Code restart.
254
- Stops the current SymNode, reconstructs it on the new service type
255
- (and optional relay), re-registers event handlers, restarts. The
256
- "smooth way to join" that was missing in 0.1.22.
257
-
258
- - **`sym_invite_create(group, relay_url?, relay_token?)`** — generate
259
- a shareable invite URL for a named group. Two flavors:
260
- - LAN-only: `sym://group/{name}` (Bonjour isolation only)
261
- - Cross-network: `sym://team/{name}?relay=...&token=...` (routes via
262
- a WebSocket relay so teammates on different networks can join).
263
- Validates kebab-case group names, rejects token without URL.
264
-
265
- - **`sym_invite_info(url)`** extended to parse the new `sym://team/`
266
- path and the `relay=` + `token=` query-string parameters.
267
- Output now includes a ready-to-paste `sym_join_group` call as JSON.
268
-
269
- - **`sym_groups_discover()`** enumerate SYM-mesh groups currently
270
- advertising on the local LAN via Bonjour / mDNS. Shell-outs to
271
- `dns-sd` (macOS/Windows) or `avahi-browse` (Linux) with a 2-second
272
- timeout, filters to service types matching the SYM protocol family
273
- (global `_sym._tcp`, named groups, `{app}-{id}` rooms). Peer-to-peer
274
- means only groups with live members right now are visible — no
275
- central directory.
276
-
277
- - **README — "Dev-team groups" walkthrough** with two concrete scenarios:
278
- LAN dev-team group (single office) and cross-network team group via
279
- the public `wss://sym-relay.onrender.com` relay. Shows exact tool
280
- calls from both the team lead and each teammate.
281
-
282
- - **13 new tests** covering invite URL parse, generate, round-trip, and
283
- validation (kebab-case, token-requires-URL guard). Test suite now at
284
- 35 tests total.
285
-
286
- ### Changed
287
-
288
- - Module-level `node`, `GROUP`, `SERVICE_TYPE`, `RELAY_URL`,
289
- `RELAY_TOKEN` declared as `let` (was `const`) so the hot-swap path
290
- can re-bind them. All node event handlers (`identity-collision`,
291
- `cmb-accepted`, `message`) extracted into a single
292
- `registerNodeHandlers(n)` function so the hot-swap path re-attaches
293
- them without duplicating logic.
294
-
295
- - Tool count in README corrected to 11 (was 8 in 0.1.22):
296
- + sym_invite_create, sym_join_group, sym_groups_discover.
297
-
298
- ## 0.1.22
299
-
300
- ### Added
301
-
302
- - **Plugin marketplace distribution**: `.claude-plugin/marketplace.json`
303
- enables direct install via the Claude Code plugin marketplace without
304
- waiting on the Anthropic Plugin Directory propagation pipeline:
305
-
306
- ```
307
- /plugin marketplace add sym-bot/sym-mesh-channel
308
- /plugin install sym-mesh-channel@sym-mesh-channel
309
- ```
310
-
311
- Validates cleanly with `claude plugin validate .` and installs
312
- end-to-end with no manual steps.
313
-
314
- - **`LICENSE`** file (Apache-2.0). `package.json` already declared
315
- Apache-2.0 but no LICENSE text was present in the repo; this
316
- aligns the distribution with SPDX expectations.
317
-
318
- - **MMP §5.8 mesh-group support** LAN isolation via Bonjour service
319
- type so Claude Code sessions can join app-specific meshes (e.g.
320
- MeloTune mood rooms on `_melotune._tcp`) instead of the global
321
- `_sym._tcp` mesh. Enables cross-app CMB delivery without cross-app
322
- noise: nodes in different groups never discover each other at mDNS.
323
-
324
- Config surface (two equivalent paths):
325
- - `SYM_GROUP=<name>` → service type `_<name>._tcp`
326
- - `SYM_SERVICE_TYPE=<st>` → explicit override (`_foo._tcp` form)
327
-
328
- Default remains `_sym._tcp` / `group=default` — backward compatible.
329
-
330
- - **Two new MCP tools for mesh-group operations**:
331
- - `sym_group_info` reports current group + service type + peer
332
- roster scoped to this group.
333
- - `sym_invite_info` parses app-specific invite URLs
334
- (`melotune://room/{id}/{name}`, `sym://group/{name}`) into service
335
- type + group + room name. Read-only inspection; caller opens a
336
- new session/env to join.
337
-
338
- `sym_status` output now includes `Group` + service type.
339
-
340
- ### Fixed
341
-
342
- - **`plugin.json` validation failure on install.** The three
343
- `channels[0].userConfig` entries (`relay_url`, `relay_token`,
344
- `allowed_peers`) were missing the required `type` and `title`
345
- fields per the Claude Code plugin schema. Install failed with:
346
-
347
- ```
348
- channels.0.userConfig.relay_url.type: Invalid option
349
- channels.0.userConfig.relay_url.title: expected string, received undefined
350
- ```
351
-
352
- Added `type: "string"` and a human-readable `title` to all three.
353
- Likely one of the root causes of the 10 Apr 2026 submission
354
- showing "Published" on the Anthropic submissions portal but not
355
- propagating to the public `claude-plugins-official` marketplace.
356
-
357
- ### Changed
358
-
359
- - **README**: self-hosted plugin-marketplace install path promoted to
360
- the primary install recommendation (works today, independent of
361
- Anthropic directory propagation). npm path kept as alternative.
362
- Tool table updated 5 8 entries to reflect the current surface.
363
- Clarified that plugin-directory approval and Channels-allowlist
364
- inclusion are independent gates — the MCP tools work without the
365
- `--dangerously-load-development-channels` flag; the flag is only
366
- needed for the `<channel>` async-push behaviour.
367
-
368
- - Pairs with `@sym-bot/sym` 0.3.78 which added the
369
- `discoveryServiceType` and `group` constructor params consumed by
370
- the mesh-group tools.
371
-
372
- ## 0.1.21
373
-
374
- ### Changed
375
-
376
- - **README: accurate `sym_status` / `sym_peers` example output.** The
377
- Quick Start sample output was a stylized one-line compression; the
378
- real output is multi-line with additional fields (nodeId suffix,
379
- Relay, Memories, one peer per line). Updated so users see in the
380
- README exactly what their terminal will show. Doc-only — no code
381
- changes.
382
-
383
- ## 0.1.20
384
-
385
- ### Added
386
-
387
- - **`sym-mesh-channel init --project`** — new flag to install the MCP
388
- server at project scope (`<cwd>/.mcp.json` + merged
389
- `<cwd>/.claude/settings.local.json`) instead of global
390
- `~/.claude.json`. Enables multi-identity-per-machine workflows where
391
- several Claude Code sessions run in parallel from distinct project
392
- directories and each appears as its own peer on the mesh. Project
393
- `.mcp.json` entries override the global `mcpServers` entry when
394
- Claude Code launches from that directory, so `SYM_NODE_NAME` can
395
- differ per project without siblings stepping on each other.
396
- - Project mode supports the same `--force` semantics as global install:
397
- backs up existing `.mcp.json` and `settings.local.json` next to
398
- themselves (`*.bak-<timestamp>`), merges `settings.local.json` so
399
- unrelated keys (permissions, custom settings) are preserved, atomic
400
- writes via tmp+rename, refuses to overwrite an existing
401
- `claude-sym-mesh` entry without `--force`.
402
- - `--postinstall` always runs global install regardless of `--project`
403
- (npm postinstall runs from npm's staging dir, not the user's
404
- project). Keeps `npm install -g` auto-configure behavior unchanged.
405
- - **5 new tests** covering project-mode install: writes `.mcp.json`
406
- and `settings.local.json`, merge preserves existing keys, refusal
407
- path exits 2, `--force` overwrite creates backup, postinstall
408
- fallback ignores `--project`. Test suite now 22 tests total.
409
-
410
- ### Why
411
-
412
- Default mode (single mesh identity per machine, global install) is
413
- correct for most users and unchanged. `--project` exists for the
414
- small but real set of users who run multiple Claude Code sessions
415
- in parallel from distinct project directories and want each session
416
- to show up as its own peer on the mesh. Previously this workflow
417
- required hand-editing `.mcp.json` and `.claude/settings.local.json`
418
- per project; now it's one command per project.
419
-
420
- ## 0.1.19
421
-
422
- ### Added
423
-
424
- - **Claude Code plugin manifest** for Anthropic Channels allowlist
425
- submission. `.claude-plugin/plugin.json` + `.mcp.json` following the
426
- official single-repo pattern (Telegram/Discord). Submitted to
427
- Anthropic Plugin Directory 10 Apr 2026.
428
- - **`SYM_ALLOWED_PEERS`** optional peer allowlist (defense-in-depth).
429
- Comma-separated node names; only listed peers can push to Claude's
430
- context. Empty = accept all authenticated peers. SVAF still gates on
431
- content relevance regardless.
432
- - **`SECURITY.md`** 3-layer defense model documentation (transport
433
- auth + SVAF content gate + peer allowlist) for Anthropic review.
434
- - **17 plugin tests** covering manifest validation, security checks
435
- (no permission relay, no code execution, self-echo filtering, peer
436
- allowlist), and lifecycle (shutdown handlers, identity collision).
437
-
438
- ## 0.1.18
439
-
440
- ### Changed
441
-
442
- - **Auto-configure on install.** `npm install -g` now runs `postinstall`
443
- that writes the MCP server config to global `mcpServers` in
444
- `~/.claude.json` automatically. No separate `sym-mesh-channel init`
445
- step needed two commands to mesh: install + launch.
446
- - **Global MCP config** server entry is now written to top-level
447
- `mcpServers` (available in all Claude Code sessions), not
448
- project-scoped.
449
- - **Windows postinstall fixes** — `require.resolve` for server.js path
450
- (handles npm staging directory on Windows), EBUSY handling when
451
- Claude Code has `~/.claude.json` locked, graceful skip if Claude
452
- Code not yet installed.
453
- - **README repositioned** lead with capability ("first non-Anthropic
454
- Claude Code Channels implementation"), not use case. Simplified
455
- Quick Start to two commands.
456
- - **0 vulnerabilities** fresh dependency rebuild resolves all 6
457
- moderate hono/node-server advisories.
458
- - Windows mDNS: built-in on Windows 10+, no Bonjour install needed.
459
-
460
- ## 0.1.7
461
-
462
- ### Added
463
-
464
- - **`npx @sym-bot/mesh-channel init`** interactive installer that
465
- writes `~/.claude.json` for the current project, picks a sensible
466
- default `SYM_NODE_NAME` (`claude-mac` / `claude-win` / `claude-linux`),
467
- resolves the absolute path to `server.js`, and prints the launch
468
- command including the `--dangerously-load-development-channels` flag.
469
- Backs up the existing config to `~/.claude.json.bak-<timestamp>`,
470
- validates JSON round-trip, atomic write via tmp+rename. Refuses to
471
- overwrite an existing entry without `--force`.
472
- - **README rewritten for LAN-first install.** Quick start is two
473
- minutes: install, init, launch. No relay required. Bonjour/mDNS
474
- is the default discovery path. Cross-network setup (relay) is now
475
- the optional advanced section.
476
-
477
- ### Changed
478
-
479
- - `package.json` `bin` now exposes both `sym-mesh-channel` (server
480
- entrypoint) and `sym-mesh-channel-init` (installer). The package
481
- description leads with "LAN-first via Bonjour, no relay required."
482
-
483
- ### Why
484
-
485
- The 0.1.5/0.1.6 install path required users to manually edit
486
- `~/.claude.json`, know about the Channels dev flag, set up a relay,
487
- and obtain a relay token. That gated the demo behind real friction.
488
- LAN-only mode has worked since day one in the underlying SymNode
489
- (`sym/lib/node.js:509-511` only connects to the relay if `SYM_RELAY_URL`
490
- is set; Bonjour discovery starts unconditionally), but no documentation
491
- or installer surfaced it. This release closes that gap: two users on
492
- the same wifi can join the same mesh in two minutes with three commands.
493
-
494
- ## 0.1.6
495
-
496
- ### Fixed
497
-
498
- - `sym_send` no longer double-delivers. Previously called both
499
- `node.send()` (broadcast as `event_type=message`) AND `node.remember()`
500
- (persist as CMB which gets gossiped as `event_type=cmb`), causing
501
- the same payload to arrive twice on receivers and double the
502
- context-window cost. Now broadcasts the message frame only. Hosts
503
- that want CMB persistence should call `sym_observe` separately
504
- with proper CAT7 fields.
505
- - `sym_send` now reports the actual delivered count, not
506
- `peers().length`. Requires `@sym-bot/sym >= 0.3.70` where `send()`
507
- returns the count of peer transports that successfully accepted
508
- the broadcast. The two can disagree when peers are tracked but
509
- have broken transports — the delivered count is the truth about
510
- what was actually sent.
511
-
512
- ### Changed
513
-
514
- - Bumped `@sym-bot/sym` dep `^0.3.69` `^0.3.70`. 0.3.70 ships the
515
- identity lockfile that prevents two SymNode processes from
516
- claiming the same nodeId on a host (the cliHostMode-vs-MCP
517
- collision that broke real-time push on Windows during the
518
- 2026-04-09 round-trip test).
519
-
520
- ## 0.1.5
521
-
522
- ### Changed
523
-
524
- - Bumped `@sym-bot/sym` dep `^0.3.68` → `^0.3.69` (0.3.68 deprecated;
525
- same code in 0.3.69 with a cleaner published tarball).
526
- - Added `files` whitelist to `package.json` and `.npmignore` for
527
- `*.bak`, `*.swp`, `.DS_Store` so future publishes can't accidentally
528
- ship local backup files. First NPM publish of this package.
529
-
530
- ## 0.1.4
531
-
532
- ### Changed
533
-
534
- - Bumped `@sym-bot/sym` dep `^0.3.43` → `^0.3.68` to pick up
535
- duplicate-identity refusal (close code 4004) and the new
536
- `identity-collision` event.
537
-
538
- ### Added
539
-
540
- - Wired `node.on('identity-collision', ...)` to `process.exit(2)` so
541
- the MCP dies cleanly when the relay reports a duplicate-identity
542
- race. Together with v0.1.3's clean shutdown, this fully resolves
543
- the host-side half of the duplicate-identity bug.
544
-
545
- ## 0.1.3
546
-
547
- ### Added
548
-
549
- - Clean shutdown handlers (SIGTERM/SIGINT/SIGHUP) that call
550
- `node.stop()` before exiting, so the SymNode disconnects from the
551
- relay before the process dies. Without this, restarts left zombie
552
- registrations on the relay until the next heartbeat tick (up to
553
- 30s), creating a duplicate-identity race window for the next MCP
554
- spawn. Idempotent re-entry guard.
555
-
556
- ## 0.1.2
557
-
558
- ### Fixed
559
-
560
- - Suppressed `peer-joined` / `peer-left` events from being pushed to
561
- Claude's context as `<channel>` notifications. Presence is high-
562
- frequency and low-signal — a relay reconnect could fire one event
563
- per peer per cycle, flooding the context window. CMBs and direct
564
- messages still flow through.
565
-
566
- ## 0.1.1
567
-
568
- ### Changed
569
-
570
- - Replaced hardcoded `claude-code` / `claude-code-mac` literals with
571
- a single `NODE_NAME` constant sourced from `process.env.SYM_NODE_NAME`
572
- (default `claude-code-mac`). Enables platform-scoped naming per
573
- MMP §3.1.2 without source edits. Fixed stale display strings in
574
- the MCP instructions, `sym_send` perspective, `sym_status` header,
575
- and the self-echo dedup filter.
576
-
577
- ## 0.1.0
578
-
579
- ### Added
580
-
581
- - Initial release. MCP server that runs a `SymNode` peer node inside
582
- a Claude Code session own identity, own relay connection, own
583
- SVAF evaluation. Tools: `sym_send`, `sym_observe`, `sym_recall`,
584
- `sym_peers`, `sym_status`. Mesh events arrive as `<channel>`
585
- notifications when launched with
586
- `claude --dangerously-load-development-channels server:claude-sym-mesh`
587
- (allowlisted server name required by Claude Code Channels).
1
+ # Changelog
2
+
3
+ ## 0.3.11
4
+
5
+ ### Added
6
+
7
+ - **Prompt-injection filter (security layer 3).** Every incoming CMB all CAT7 fields and the opaque payload is now scanned against a curated blocklist of injection patterns before `pushChannel()` is called. Patterns cover: instruction-override phrases ("ignore previous instructions", "forget everything you know"), role/persona hijacking ("you are now a new AI", "act as an unrestricted assistant"), system-prompt injection (`<system>`, `[SYSTEM]`, `## system prompt`), tool-call fabrication (`<tool_call>`, `<function_calls>`), and privilege-escalation language ("override safety filter", "jailbreak", "DAN mode"). Blocked CMBs are audit-logged to stderr with reason, peer name, and a truncated excerpt — never silently dropped.
8
+
9
+ - **Per-peer rate limiting.** A sliding 60-second window caps each peer at `SYM_RATE_LIMIT` CMBs per minute (default: 30). CMBs exceeding the cap are blocked and audit-logged. Prevents flood attacks from a compromised or malfunctioning peer.
10
+
11
+ - **Payload size cap.** Payloads larger than `SYM_MAX_PAYLOAD_BYTES` (default: 8 192 bytes) are rejected before context injection. Prevents oversized-payload attacks that could exhaust the context window.
12
+
13
+ - **README security section updated** to document all four defence layers accurately.
14
+
15
+ ### Security model
16
+
17
+ The full gate before any mesh signal reaches Claude's context is now:
18
+ 1. **Transport** — Ed25519 peer identity + relay-token auth.
19
+ 2. **Protocol** — SVAF per-field semantic relevance gate.
20
+ 3. **Safety** prompt-injection filter + rate limiter + payload size cap (this release).
21
+ 4. **Application** text-only injection; `claude/channel/permission` not declared.
22
+
23
+ ## 0.3.10
24
+
25
+ ### Fixed
26
+
27
+ - **Live-identity-collision auto-suffix.** Two sessions wanting the same `SYM_NODE_NAME` previously hard-failed with `EIDENTITYLOCK`. The server now checks whether the name's lock file is held by a live process; if so, it appends `-2`, `-3`, … (up to 64) until it finds a free slot. Stale locks (dead holder) are still reclaimed by `@sym-bot/sym` on start — unchanged. Result: duplicate dev-agent sessions, or any two sessions sharing a fixed `SYM_NODE_NAME`, coexist instead of failing.
28
+
29
+ ## 0.3.9
30
+
31
+ ### Fixed
32
+
33
+ - **stdout discipline — fixes `-32000 / Connection closed`.** The MCP JSON-RPC stream runs on stdout. Dependency load banners (e.g. `[encoder] Semantic encoder ready` from the semantic model) were printing to stdout, intermittently corrupting the handshake and causing Claude Code to log "Ignoring non-JSON line on stdout" or drop the connection with `-32000`. A stdout guard is now installed before any `require()`: lines that start with `{` (JSON-RPC frames) pass through to the real stdout; everything else is redirected to stderr. Verified: stdout is pure JSON after the fix.
34
+
35
+ ## 0.3.8
36
+
37
+ ### Added
38
+
39
+ - **Per-session node identity.** Each Claude Code session now gets its own mesh identity derived from the working-directory slug and a session-unique suffix (e.g. `claude-symday-webapp-6e174e`), instead of all sessions sharing the machine hostname. Enables multiple Claude Code sessions on the same machine to appear as distinct peers on the mesh — confirmed working over loopback via Bonjour with no relay.
40
+
41
+ - **`npx` launch path.** The plugin now launches via `npx @sym-bot/mesh-channel` rather than a global `node` path, so marketplace installs work without a prior `npm install -g`. The npx cache warms on first launch; subsequent sessions start in ~1 s.
42
+
43
+ ## 0.3.7
44
+
45
+ ### Changed
46
+
47
+ - **Bumped `@sym-bot/sym` dependency `^0.5.8` → `^0.7.4`** to track the current sym stack. The range had drifted: sym moved through 0.6.x/0.7.x (mesh groups, Windows portability) while this wrapper still declared `^0.5.8`, so an installed sym ≥0.6 showed as `invalid` and a reinstall could nest a stale 0.5.x that shadows the global. Pinning `^0.7.4` makes the dependency honest and, in particular, **requires the loopback-capable sym (≥0.7.4)** — co-resident nodes mesh over `127.0.0.1` with no network interface (Wi-Fi off). No code change in this package; dependency-range correctness only.
48
+
49
+ ## 0.3.6
50
+
51
+ ### Added
52
+
53
+ - **Group discovery beacon.** This MCP node now advertises its mesh group on a shared `_symgroups._tcp` service (group name in TXT) via the pure-JS `bonjour-service` — published on start, re-published on `sym_join_group` hot-swap, torn down on shutdown. Makes the Claude/MCP node discoverable by the `sym` CLI's `sym groups` command **cross-platform, including Windows** (where Apple's `dns-sd` is absent), so CLI-daemon and Claude/MCP nodes list together. Discovery-only — comms stay isolated on the group's own `_<group>._tcp`. `bonjour-service` pinned as a direct dependency. Validated on Windows 11.
54
+ - **Operational note:** a session started before 0.3.6 must restart to begin beaconing.
55
+
56
+ ## 0.3.5
57
+
58
+ ### Added
59
+
60
+ - **Opaque payload on `sym_send` / `sym_observe`.** Both tools accept
61
+ an optional `payload` argument carrying data beyond CAT7 any
62
+ JSON-serializable value. Forwarded to `SymNode.remember(fields, {
63
+ payload, })` (requires `@sym-bot/sym` ≥ 0.5.8) and rides the wire
64
+ frame to peers. Used by substrate-level protocols that need to carry
65
+ structured data alongside CAT7 (e.g. LLM request/response, where the
66
+ prompt + request_id ride in `payload` rather than getting smuggled
67
+ through `motivation`).
68
+ - **Channel notifications surface payload-bearing CMBs.** When an
69
+ incoming peer CMB carries `cmb.payload`, the header gains a
70
+ `[+payload Nb]` indicator and the body stored by `sym_fetch`
71
+ includes a `---PAYLOAD---` section with the serialized payload.
72
+ Receivers learn from the header that there's structured data beyond
73
+ CAT7 and call `sym_fetch` to consume it.
74
+ - Base MCP instructions now teach agents to recognise the
75
+ `[+payload Nb]` header and to pass structured responses via the
76
+ `payload` argument when emitting substrate-level CMBs.
77
+
78
+ ### Compatibility
79
+
80
+ - Omitting `payload` produces a v0.3.4-shaped CAT7 CMB byte-for-byte.
81
+ - Old peers (without `cmb.payload`) surface unchanged headers — no
82
+ `[+payload …]` indicator, no PAYLOAD section in the body.
83
+
84
+ ## 0.3.4
85
+
86
+ ### Added
87
+
88
+ - **`SYM_GROUP` is now first-class in the installer.** `init` accepts a
89
+ `--group <name>` flag and reads the `SYM_GROUP` env var; both paths
90
+ persist the chosen group into the `~/.claude.json` (or project
91
+ `.mcp.json`) env block so every Claude Code launch auto-joins the
92
+ named group instead of the global `_sym._tcp` mesh.
93
+
94
+ Resolution order is `--force`-aware:
95
+ - With `--force` and an explicit `--group`/`SYM_GROUP`: flag/env wins
96
+ (one-command group switch on a live entry).
97
+ - Without `--force`, or with `--force` but no explicit value:
98
+ preserved value from any existing entry > explicit > none (omit).
99
+
100
+ `--force --group default` (or `SYM_GROUP=default`) is the explicit
101
+ escape hatch to revert a node from a named group back to the global
102
+ mesh — removes `SYM_GROUP` from the env block entirely rather than
103
+ writing the literal string "default".
104
+
105
+ Both `--group` and `SYM_GROUP` env values are validated against the
106
+ same kebab-case regex; malformed values exit with a clear error
107
+ before any file write.
108
+
109
+ - **`doctor` now reports the persisted group per entry** and warns when
110
+ user-global and project-scoped entries disagree on `SYM_GROUP`.
111
+ Group-mismatch is the most common cause of "peers never appear in
112
+ `sym_peers`" with no other failure signal surfacing it inline saves
113
+ the diagnostic walk that motivated this release.
114
+
115
+ - **README** gains a "Persisting your group across restarts" subsection
116
+ under Team mesh groups, plus a troubleshooting entry covering the
117
+ group-mismatch failure mode. Quick-start shows the `--group` flag.
118
+
119
+ ### Fixed
120
+
121
+ - **Stale-entry heal preserves `SYM_GROUP` alongside `SYM_NODE_NAME`.**
122
+ Previously, healing a stale `claude-sym-mesh` entry (args[0] points at
123
+ a missing server.js) silently dropped any persisted `SYM_GROUP`,
124
+ reverting the node to the default mesh on next launch and stranding
125
+ teammates who stayed in the named group. The heal path now copies
126
+ both fields from the prior entry into the rewrite.
127
+
128
+ Same fix applied to project-scoped entry healing under
129
+ `claudeJson.projects[<path>].mcpServers`.
130
+
131
+ ### Why this matters
132
+
133
+ Before 0.3.4, the only way to persist a group was to hand-edit
134
+ `~/.claude.json`. The README pitched `sym_join_group` as the team-mesh
135
+ UX, but that tool is runtime-only the next Claude Code launch reverted
136
+ the node to the default mesh, peer count dropped to zero, and the user
137
+ saw no diagnostic signal. The 2026-05-02 SYM.BOT incident (CMO in
138
+ `default`, COO in `sym-bot-team`, ~24h of silent duplex outage) traced
139
+ directly to this gap.
140
+
141
+ ## 0.3.3
142
+
143
+ ### Fixed
144
+
145
+ - **Real-time duplex for CAT7 CMBs.** The `cmb-accepted` handler now
146
+ stores the rendered CMB body under an `[mNNN]` ID and includes that
147
+ ID in the channel notification, matching the contract stated in the
148
+ MCP instructions ("Messages arrive as compact headers with [mNNN] IDs
149
+ use sym_fetch to read the full content") and the behaviour of the
150
+ raw-text `message` path.
151
+
152
+ Previously only the legacy raw-text `message` event persisted bodies
153
+ to `MESSAGE_STORE` the primary `cmb-accepted` event (fired for
154
+ every structured CMB delivered via `sym_send` / `sym_observe`) pushed
155
+ a headline with no `[mNNN]` and left no retrievable body. Inbound
156
+ CMBs were admitted to the SVAF-backed memory store and surfaced by
157
+ `sym_recall` as compact headlines, but `sym_fetch` could not return
158
+ their content the duplex was effectively headline-only for the 99%
159
+ case of real mesh traffic.
160
+
161
+ Symptom: after the 0.3.2 Mac↔Win fix restored bidirectional packet
162
+ flow, peers' structured replies appeared in `sym_recall` but returned
163
+ *"expired or invalid ID"* from `sym_fetch` because `storeMessage()`
164
+ had never been called for them. Now both the raw-text and CAT7 paths
165
+ persist bodies identically.
166
+
167
+ ## 0.3.2
168
+
169
+ ### Fixed
170
+
171
+ - **Pulls in `@sym-bot/sym` 0.5.1** — fixes Mac↔Windows peer connections
172
+ over LAN. Prior releases shipped a Bonjour advertisement whose SRV
173
+ target was the bare Windows NetBIOS hostname (e.g. `xmesh-hp.`) with
174
+ no `.local` suffix. macOS mDNSResponder only resolves `.local.` mDNS
175
+ names, so Macs could discover Windows peers via bonjour browse but
176
+ failed to open the outbound TCP connection. CMBs targeted at Windows
177
+ nodes never arrived; no replies came back. Full diagnosis in sym
178
+ 0.5.1 CHANGELOG.
179
+
180
+ Upgrade required on both sides to restore Mac↔Windows traffic.
181
+ Existing Windows identities with a bare hostname are auto-migrated
182
+ on next node start; no manual config edit needed.
183
+
184
+ ## 0.3.1
185
+
186
+ ### Fixed
187
+
188
+ - **Installer no longer silently ships a broken MCP config.** Previously,
189
+ if `~/.claude.json` already contained a `claude-sym-mesh` entry,
190
+ `npm install -g @sym-bot/mesh-channel` (via postinstall) and
191
+ `npx @sym-bot/mesh-channel init` both skipped with "already configured"
192
+ even when the entry's `args[0]` server.js path no longer existed on
193
+ disk (common after moving or reinstalling the repo). Users saw
194
+ `/mcp` report "Failed to reconnect" with no diagnostic hint.
195
+
196
+ The installer now classifies entries whose `args[0]` is missing as
197
+ **stale** and rewrites them automatically without `--force`, preserving
198
+ `SYM_NODE_NAME` from the prior entry so mesh identity doesn't drift
199
+ back to the hostname-based default. Live entries continue to require
200
+ `--force` for overwrite.
201
+
202
+ - **Stale project-scoped entries are now healed too.** `~/.claude.json`
203
+ can carry per-project `mcpServers` overrides under
204
+ `projects.<dir>.mcpServers`, and Claude Code prefers those over the
205
+ user-global entry when launched from that directory. A healthy
206
+ user-global entry was therefore being silently shadowed by stale
207
+ project entries. `init` now scans every project, rewrites any stale
208
+ `claude-sym-mesh` entry, and preserves each project's `SYM_NODE_NAME`.
209
+
210
+ ### Added
211
+
212
+ - **`sym-mesh-channel doctor` subcommand.** Read-only diagnostic that
213
+ lists every `claude-sym-mesh` entry in `~/.claude.json` (user-global
214
+ and every project scope) with `[live]` or `[STALE]` plus its
215
+ `SYM_NODE_NAME` and configured path. Point users here when `/mcp`
216
+ reports "Failed to reconnect". No writes, safe to run any time.
217
+
218
+ - **README troubleshooting section** covering the `/mcp` failure path,
219
+ how to run `doctor`, and when restart is needed after a config change.
220
+
221
+ ### Changed
222
+
223
+ - `.claude-plugin/plugin.json` version field bumped to `0.3.1` to match
224
+ `package.json`. Previous drift (`plugin.json` stuck at `0.2.0`, package
225
+ at `0.3.0`) was caught by the in-repo version-parity test.
226
+
227
+ ## 0.3.0
228
+
229
+ ### Added
230
+
231
+ - **Startup remix-memory primer automates agent memory recall on
232
+ session/agent restart (MMP §4.2 O2, rejoin-without-replay).** As the
233
+ final step of plugin initialisation (after `node.start()` and before
234
+ the MCP transport connects), the plugin calls
235
+ `node.buildStartupPrimer()` and appends the returned text to the MCP
236
+ server's `instructions` field. A fresh Claude Code session wakes
237
+ with the agent's own remix memory — own observations plus peer
238
+ observations admitted by SVAF already loaded into context. No
239
+ first-turn `sym_recall` required; agent acts from prior state
240
+ immediately.
241
+
242
+ Default caps: last 24 hours OR 20 most recent CMBs, whichever is
243
+ tighter. The primer lists each entry as `[timestamp] source · key
244
+ focus` and surfaces a dropped-count line when caps elide older
245
+ entries. Empty store is a silent no-op.
246
+
247
+ ### Changed
248
+
249
+ - **`@sym-bot/sym` dep bumped to `^0.5.0`** to pick up the
250
+ `buildStartupPrimer` helper and to keep every plugin on the
251
+ sym.day platform pinned to the same substrate SDK version
252
+ (no drift across mesh-channel / melotune-plugin / future
253
+ specialised plugins).
254
+
255
+ ## 0.2.0
256
+
257
+ ### Breaking
258
+
259
+ - **`sym_send` tool signature change.** `sym_send` now emits a structured
260
+ CAT7 CMB (MMP §4.2) instead of a raw-text `type:'message'` frame, and
261
+ accepts an optional `to` parameter for targeted single-peer delivery
262
+ per MMP §4.4.4.
263
+
264
+ Old signature: `sym_send(message: string)`
265
+ New signature: `sym_send(focus: string (required), issue?, intent?,
266
+ motivation?, commitment?, perspective?, mood?, to?)`
267
+
268
+ Migration: agents that previously called `sym_send({message: "..."})`
269
+ should now pass the CAT7 fields explicitly, with `focus` carrying the
270
+ task anchor for the send. Prior ephemeral text-broadcast behaviour is
271
+ no longer exposed at the tool surface — `sym_send` and `sym_observe`
272
+ both emit CMBs now, receivers run SVAF per §9.2, and admitted CMBs are
273
+ remix-stored with lineage. The low-level `node.send(text)` SDK API is
274
+ unchanged but no longer surfaced as a tool.
275
+
276
+ ### Added
277
+
278
+ - **Targeted CMB send.** `sym_send` resolves `to` against connected
279
+ peers by full nodeId first, then display name, then 8-char prefix.
280
+ Ambiguous matches return an error asking for the full nodeId; a
281
+ disconnected target returns an error and suggests `sym_peers`.
282
+ - **Tool descriptions** for `sym_send` and `sym_observe` now explicitly
283
+ call out the SVAF receive path and lineage semantics, and the MCP
284
+ server's `instructions` string reflects the new division of labour.
285
+ - **`@sym-bot/sym` dependency bumped to `^0.3.81`** for
286
+ `remember(fields, {to})` targeted variant and `peers().peerId`.
287
+
288
+ ## 0.1.23
289
+
290
+ ### Added
291
+
292
+ - **`sym_join_group(group, relay_url?, relay_token?)`** hot-swap this
293
+ node into a different mesh group at runtime, no Claude Code restart.
294
+ Stops the current SymNode, reconstructs it on the new service type
295
+ (and optional relay), re-registers event handlers, restarts. The
296
+ "smooth way to join" that was missing in 0.1.22.
297
+
298
+ - **`sym_invite_create(group, relay_url?, relay_token?)`** — generate
299
+ a shareable invite URL for a named group. Two flavors:
300
+ - LAN-only: `sym://group/{name}` (Bonjour isolation only)
301
+ - Cross-network: `sym://team/{name}?relay=...&token=...` (routes via
302
+ a WebSocket relay so teammates on different networks can join).
303
+ Validates kebab-case group names, rejects token without URL.
304
+
305
+ - **`sym_invite_info(url)`** extended to parse the new `sym://team/`
306
+ path and the `relay=` + `token=` query-string parameters.
307
+ Output now includes a ready-to-paste `sym_join_group` call as JSON.
308
+
309
+ - **`sym_groups_discover()`** — enumerate SYM-mesh groups currently
310
+ advertising on the local LAN via Bonjour / mDNS. Shell-outs to
311
+ `dns-sd` (macOS/Windows) or `avahi-browse` (Linux) with a 2-second
312
+ timeout, filters to service types matching the SYM protocol family
313
+ (global `_sym._tcp`, named groups, `{app}-{id}` rooms). Peer-to-peer
314
+ means only groups with live members right now are visible — no
315
+ central directory.
316
+
317
+ - **README — "Dev-team groups" walkthrough** with two concrete scenarios:
318
+ LAN dev-team group (single office) and cross-network team group via
319
+ the public `wss://sym-relay.onrender.com` relay. Shows exact tool
320
+ calls from both the team lead and each teammate.
321
+
322
+ - **13 new tests** covering invite URL parse, generate, round-trip, and
323
+ validation (kebab-case, token-requires-URL guard). Test suite now at
324
+ 35 tests total.
325
+
326
+ ### Changed
327
+
328
+ - Module-level `node`, `GROUP`, `SERVICE_TYPE`, `RELAY_URL`,
329
+ `RELAY_TOKEN` declared as `let` (was `const`) so the hot-swap path
330
+ can re-bind them. All node event handlers (`identity-collision`,
331
+ `cmb-accepted`, `message`) extracted into a single
332
+ `registerNodeHandlers(n)` function so the hot-swap path re-attaches
333
+ them without duplicating logic.
334
+
335
+ - Tool count in README corrected to 11 (was 8 in 0.1.22):
336
+ + sym_invite_create, sym_join_group, sym_groups_discover.
337
+
338
+ ## 0.1.22
339
+
340
+ ### Added
341
+
342
+ - **Plugin marketplace distribution**: `.claude-plugin/marketplace.json`
343
+ enables direct install via the Claude Code plugin marketplace without
344
+ waiting on the Anthropic Plugin Directory propagation pipeline:
345
+
346
+ ```
347
+ /plugin marketplace add sym-bot/sym-mesh-channel
348
+ /plugin install sym-mesh-channel@sym-mesh-channel
349
+ ```
350
+
351
+ Validates cleanly with `claude plugin validate .` and installs
352
+ end-to-end with no manual steps.
353
+
354
+ - **`LICENSE`** file (Apache-2.0). `package.json` already declared
355
+ Apache-2.0 but no LICENSE text was present in the repo; this
356
+ aligns the distribution with SPDX expectations.
357
+
358
+ - **MMP §5.8 mesh-group support** — LAN isolation via Bonjour service
359
+ type so Claude Code sessions can join app-specific meshes (e.g.
360
+ MeloTune mood rooms on `_melotune._tcp`) instead of the global
361
+ `_sym._tcp` mesh. Enables cross-app CMB delivery without cross-app
362
+ noise: nodes in different groups never discover each other at mDNS.
363
+
364
+ Config surface (two equivalent paths):
365
+ - `SYM_GROUP=<name>` → service type `_<name>._tcp`
366
+ - `SYM_SERVICE_TYPE=<st>` → explicit override (`_foo._tcp` form)
367
+
368
+ Default remains `_sym._tcp` / `group=default` backward compatible.
369
+
370
+ - **Two new MCP tools for mesh-group operations**:
371
+ - `sym_group_info` — reports current group + service type + peer
372
+ roster scoped to this group.
373
+ - `sym_invite_info` — parses app-specific invite URLs
374
+ (`melotune://room/{id}/{name}`, `sym://group/{name}`) into service
375
+ type + group + room name. Read-only inspection; caller opens a
376
+ new session/env to join.
377
+
378
+ `sym_status` output now includes `Group` + service type.
379
+
380
+ ### Fixed
381
+
382
+ - **`plugin.json` validation failure on install.** The three
383
+ `channels[0].userConfig` entries (`relay_url`, `relay_token`,
384
+ `allowed_peers`) were missing the required `type` and `title`
385
+ fields per the Claude Code plugin schema. Install failed with:
386
+
387
+ ```
388
+ channels.0.userConfig.relay_url.type: Invalid option
389
+ channels.0.userConfig.relay_url.title: expected string, received undefined
390
+ ```
391
+
392
+ Added `type: "string"` and a human-readable `title` to all three.
393
+ Likely one of the root causes of the 10 Apr 2026 submission
394
+ showing "Published" on the Anthropic submissions portal but not
395
+ propagating to the public `claude-plugins-official` marketplace.
396
+
397
+ ### Changed
398
+
399
+ - **README**: self-hosted plugin-marketplace install path promoted to
400
+ the primary install recommendation (works today, independent of
401
+ Anthropic directory propagation). npm path kept as alternative.
402
+ Tool table updated 5 8 entries to reflect the current surface.
403
+ Clarified that plugin-directory approval and Channels-allowlist
404
+ inclusion are independent gates the MCP tools work without the
405
+ `--dangerously-load-development-channels` flag; the flag is only
406
+ needed for the `<channel>` async-push behaviour.
407
+
408
+ - Pairs with `@sym-bot/sym` 0.3.78 which added the
409
+ `discoveryServiceType` and `group` constructor params consumed by
410
+ the mesh-group tools.
411
+
412
+ ## 0.1.21
413
+
414
+ ### Changed
415
+
416
+ - **README: accurate `sym_status` / `sym_peers` example output.** The
417
+ Quick Start sample output was a stylized one-line compression; the
418
+ real output is multi-line with additional fields (nodeId suffix,
419
+ Relay, Memories, one peer per line). Updated so users see in the
420
+ README exactly what their terminal will show. Doc-only — no code
421
+ changes.
422
+
423
+ ## 0.1.20
424
+
425
+ ### Added
426
+
427
+ - **`sym-mesh-channel init --project`** new flag to install the MCP
428
+ server at project scope (`<cwd>/.mcp.json` + merged
429
+ `<cwd>/.claude/settings.local.json`) instead of global
430
+ `~/.claude.json`. Enables multi-identity-per-machine workflows where
431
+ several Claude Code sessions run in parallel from distinct project
432
+ directories and each appears as its own peer on the mesh. Project
433
+ `.mcp.json` entries override the global `mcpServers` entry when
434
+ Claude Code launches from that directory, so `SYM_NODE_NAME` can
435
+ differ per project without siblings stepping on each other.
436
+ - Project mode supports the same `--force` semantics as global install:
437
+ backs up existing `.mcp.json` and `settings.local.json` next to
438
+ themselves (`*.bak-<timestamp>`), merges `settings.local.json` so
439
+ unrelated keys (permissions, custom settings) are preserved, atomic
440
+ writes via tmp+rename, refuses to overwrite an existing
441
+ `claude-sym-mesh` entry without `--force`.
442
+ - `--postinstall` always runs global install regardless of `--project`
443
+ (npm postinstall runs from npm's staging dir, not the user's
444
+ project). Keeps `npm install -g` auto-configure behavior unchanged.
445
+ - **5 new tests** covering project-mode install: writes `.mcp.json`
446
+ and `settings.local.json`, merge preserves existing keys, refusal
447
+ path exits 2, `--force` overwrite creates backup, postinstall
448
+ fallback ignores `--project`. Test suite now 22 tests total.
449
+
450
+ ### Why
451
+
452
+ Default mode (single mesh identity per machine, global install) is
453
+ correct for most users and unchanged. `--project` exists for the
454
+ small but real set of users who run multiple Claude Code sessions
455
+ in parallel from distinct project directories and want each session
456
+ to show up as its own peer on the mesh. Previously this workflow
457
+ required hand-editing `.mcp.json` and `.claude/settings.local.json`
458
+ per project; now it's one command per project.
459
+
460
+ ## 0.1.19
461
+
462
+ ### Added
463
+
464
+ - **Claude Code plugin manifest** for Anthropic Channels allowlist
465
+ submission. `.claude-plugin/plugin.json` + `.mcp.json` following the
466
+ official single-repo pattern (Telegram/Discord). Submitted to
467
+ Anthropic Plugin Directory 10 Apr 2026.
468
+ - **`SYM_ALLOWED_PEERS`** optional peer allowlist (defense-in-depth).
469
+ Comma-separated node names; only listed peers can push to Claude's
470
+ context. Empty = accept all authenticated peers. SVAF still gates on
471
+ content relevance regardless.
472
+ - **`SECURITY.md`** 3-layer defense model documentation (transport
473
+ auth + SVAF content gate + peer allowlist) for Anthropic review.
474
+ - **17 plugin tests** covering manifest validation, security checks
475
+ (no permission relay, no code execution, self-echo filtering, peer
476
+ allowlist), and lifecycle (shutdown handlers, identity collision).
477
+
478
+ ## 0.1.18
479
+
480
+ ### Changed
481
+
482
+ - **Auto-configure on install.** `npm install -g` now runs `postinstall`
483
+ that writes the MCP server config to global `mcpServers` in
484
+ `~/.claude.json` automatically. No separate `sym-mesh-channel init`
485
+ step needed two commands to mesh: install + launch.
486
+ - **Global MCP config** server entry is now written to top-level
487
+ `mcpServers` (available in all Claude Code sessions), not
488
+ project-scoped.
489
+ - **Windows postinstall fixes** `require.resolve` for server.js path
490
+ (handles npm staging directory on Windows), EBUSY handling when
491
+ Claude Code has `~/.claude.json` locked, graceful skip if Claude
492
+ Code not yet installed.
493
+ - **README repositioned** — lead with capability ("first non-Anthropic
494
+ Claude Code Channels implementation"), not use case. Simplified
495
+ Quick Start to two commands.
496
+ - **0 vulnerabilities** — fresh dependency rebuild resolves all 6
497
+ moderate hono/node-server advisories.
498
+ - Windows mDNS: built-in on Windows 10+, no Bonjour install needed.
499
+
500
+ ## 0.1.7
501
+
502
+ ### Added
503
+
504
+ - **`npx @sym-bot/mesh-channel init`** — interactive installer that
505
+ writes `~/.claude.json` for the current project, picks a sensible
506
+ default `SYM_NODE_NAME` (`claude-mac` / `claude-win` / `claude-linux`),
507
+ resolves the absolute path to `server.js`, and prints the launch
508
+ command including the `--dangerously-load-development-channels` flag.
509
+ Backs up the existing config to `~/.claude.json.bak-<timestamp>`,
510
+ validates JSON round-trip, atomic write via tmp+rename. Refuses to
511
+ overwrite an existing entry without `--force`.
512
+ - **README rewritten for LAN-first install.** Quick start is two
513
+ minutes: install, init, launch. No relay required. Bonjour/mDNS
514
+ is the default discovery path. Cross-network setup (relay) is now
515
+ the optional advanced section.
516
+
517
+ ### Changed
518
+
519
+ - `package.json` `bin` now exposes both `sym-mesh-channel` (server
520
+ entrypoint) and `sym-mesh-channel-init` (installer). The package
521
+ description leads with "LAN-first via Bonjour, no relay required."
522
+
523
+ ### Why
524
+
525
+ The 0.1.5/0.1.6 install path required users to manually edit
526
+ `~/.claude.json`, know about the Channels dev flag, set up a relay,
527
+ and obtain a relay token. That gated the demo behind real friction.
528
+ LAN-only mode has worked since day one in the underlying SymNode
529
+ (`sym/lib/node.js:509-511` only connects to the relay if `SYM_RELAY_URL`
530
+ is set; Bonjour discovery starts unconditionally), but no documentation
531
+ or installer surfaced it. This release closes that gap: two users on
532
+ the same wifi can join the same mesh in two minutes with three commands.
533
+
534
+ ## 0.1.6
535
+
536
+ ### Fixed
537
+
538
+ - `sym_send` no longer double-delivers. Previously called both
539
+ `node.send()` (broadcast as `event_type=message`) AND `node.remember()`
540
+ (persist as CMB which gets gossiped as `event_type=cmb`), causing
541
+ the same payload to arrive twice on receivers and double the
542
+ context-window cost. Now broadcasts the message frame only. Hosts
543
+ that want CMB persistence should call `sym_observe` separately
544
+ with proper CAT7 fields.
545
+ - `sym_send` now reports the actual delivered count, not
546
+ `peers().length`. Requires `@sym-bot/sym >= 0.3.70` where `send()`
547
+ returns the count of peer transports that successfully accepted
548
+ the broadcast. The two can disagree when peers are tracked but
549
+ have broken transports the delivered count is the truth about
550
+ what was actually sent.
551
+
552
+ ### Changed
553
+
554
+ - Bumped `@sym-bot/sym` dep `^0.3.69` → `^0.3.70`. 0.3.70 ships the
555
+ identity lockfile that prevents two SymNode processes from
556
+ claiming the same nodeId on a host (the cliHostMode-vs-MCP
557
+ collision that broke real-time push on Windows during the
558
+ 2026-04-09 round-trip test).
559
+
560
+ ## 0.1.5
561
+
562
+ ### Changed
563
+
564
+ - Bumped `@sym-bot/sym` dep `^0.3.68` → `^0.3.69` (0.3.68 deprecated;
565
+ same code in 0.3.69 with a cleaner published tarball).
566
+ - Added `files` whitelist to `package.json` and `.npmignore` for
567
+ `*.bak`, `*.swp`, `.DS_Store` so future publishes can't accidentally
568
+ ship local backup files. First NPM publish of this package.
569
+
570
+ ## 0.1.4
571
+
572
+ ### Changed
573
+
574
+ - Bumped `@sym-bot/sym` dep `^0.3.43` `^0.3.68` to pick up
575
+ duplicate-identity refusal (close code 4004) and the new
576
+ `identity-collision` event.
577
+
578
+ ### Added
579
+
580
+ - Wired `node.on('identity-collision', ...)` to `process.exit(2)` so
581
+ the MCP dies cleanly when the relay reports a duplicate-identity
582
+ race. Together with v0.1.3's clean shutdown, this fully resolves
583
+ the host-side half of the duplicate-identity bug.
584
+
585
+ ## 0.1.3
586
+
587
+ ### Added
588
+
589
+ - Clean shutdown handlers (SIGTERM/SIGINT/SIGHUP) that call
590
+ `node.stop()` before exiting, so the SymNode disconnects from the
591
+ relay before the process dies. Without this, restarts left zombie
592
+ registrations on the relay until the next heartbeat tick (up to
593
+ 30s), creating a duplicate-identity race window for the next MCP
594
+ spawn. Idempotent re-entry guard.
595
+
596
+ ## 0.1.2
597
+
598
+ ### Fixed
599
+
600
+ - Suppressed `peer-joined` / `peer-left` events from being pushed to
601
+ Claude's context as `<channel>` notifications. Presence is high-
602
+ frequency and low-signal — a relay reconnect could fire one event
603
+ per peer per cycle, flooding the context window. CMBs and direct
604
+ messages still flow through.
605
+
606
+ ## 0.1.1
607
+
608
+ ### Changed
609
+
610
+ - Replaced hardcoded `claude-code` / `claude-code-mac` literals with
611
+ a single `NODE_NAME` constant sourced from `process.env.SYM_NODE_NAME`
612
+ (default `claude-code-mac`). Enables platform-scoped naming per
613
+ MMP §3.1.2 without source edits. Fixed stale display strings in
614
+ the MCP instructions, `sym_send` perspective, `sym_status` header,
615
+ and the self-echo dedup filter.
616
+
617
+ ## 0.1.0
618
+
619
+ ### Added
620
+
621
+ - Initial release. MCP server that runs a `SymNode` peer node inside
622
+ a Claude Code session — own identity, own relay connection, own
623
+ SVAF evaluation. Tools: `sym_send`, `sym_observe`, `sym_recall`,
624
+ `sym_peers`, `sym_status`. Mesh events arrive as `<channel>`
625
+ notifications when launched with
626
+ `claude --dangerously-load-development-channels server:claude-sym-mesh`
627
+ (allowlisted server name required by Claude Code Channels).