@sym-bot/mesh-channel 0.3.4 → 0.3.6

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