@sym-bot/mesh-channel 0.3.14 → 0.3.15

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/.mcp.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "command": "npx",
5
5
  "args": [
6
6
  "-y",
7
- "@sym-bot/mesh-channel@0.3.10"
7
+ "@sym-bot/mesh-channel@0.3.14"
8
8
  ],
9
9
  "env": {
10
10
  "SYM_RELAY_URL": "${user_config.relay_url}",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.15
4
+
5
+ ### Fixed
6
+
7
+ - **`start` now finds `claude` on Windows.** The launch used `spawnSync('claude', …)` with no shell, which does an exact-filename lookup that ignores Windows `PATHEXT` — so `start` failed with `ENOENT` even when `claude` ran fine in the shell (there it resolves a `.cmd`/`.ps1` shim or `.exe`, never bare `claude`). The launch now routes through a shell on Windows so `PATHEXT` resolution applies; whitespace args are quoted since `shell: true` forwards them unquoted. The POSIX launch path is unchanged.
8
+ - **`start --name` no longer silently reverts identity on a stale entry.** `start` auto-injected `--force` only on a *live* entry mismatch, but `npx` rotates its cached `server.js` path on every version resolve, so the persisted entry is routinely stale yet still holds the node's name/group. On a re-run, `start` saw no live entry, pushed no `--force`, and `init`'s preserve-over-request precedence dropped the requested `--name` — reverting the node's identity to the stale name. `start` now reconciles against the persisted entry whether or not it's stale and forces the rewrite when an explicit `--name`/`--group` differs. The group is preserved when no `--group` is passed.
9
+
3
10
  ## 0.3.14
4
11
 
5
12
  ### Added
package/bin/install.js CHANGED
@@ -151,19 +151,26 @@ if (cmd === 'start') {
151
151
 
152
152
  // Is the scope Claude Code will actually read already configured with a
153
153
  // LIVE entry? --project → <cwd>/.mcp.json ; otherwise → ~/.claude.json
154
- function liveEntryInScope() {
154
+ // Reconcile identity against the persisted entry whether or not its
155
+ // server.js path is stale. npx rotates the cached server.js path on every
156
+ // version resolve (…/_npx/<hash>/…), so the entry is routinely stale yet
157
+ // still carries the node's name/group. Comparing only against a *live*
158
+ // entry let an explicit --name lose to the stale name on the heal path:
159
+ // start saw no live entry, pushed no --force, and init's non-force
160
+ // precedence (preserve-over-request) kept the old identity.
161
+ function rawEntryInScope() {
155
162
  try {
156
163
  const p = isProject
157
164
  ? path.join(launchDir, '.mcp.json')
158
165
  : path.join(os.homedir(), '.claude.json');
159
166
  if (!fs.existsSync(p)) return null;
160
167
  const j = JSON.parse(fs.readFileSync(p, 'utf8'));
161
- const e = j && j.mcpServers && j.mcpServers['claude-sym-mesh'];
162
- return e && !isStaleEntry(e) ? e : null;
168
+ return (j && j.mcpServers && j.mcpServers['claude-sym-mesh']) || null;
163
169
  } catch { return null; }
164
170
  }
165
171
 
166
- const existing = liveEntryInScope();
172
+ const existing = rawEntryInScope();
173
+ const stale = existing ? isStaleEntry(existing) : false;
167
174
  const wantName = nameArg || null;
168
175
  const wantGroup = groupArg || null;
169
176
  const mismatch = !!existing && (
@@ -171,13 +178,19 @@ if (cmd === 'start') {
171
178
  (wantGroup && (preserveGroup(existing) || 'default') !== wantGroup)
172
179
  );
173
180
 
174
- // Configure only when there's nothing live yet, an explicit --name/--group
175
- // differs from the current entry, or --force was passed. Otherwise launch
176
- // straight away — `start` stays cheap to run every session.
177
- if (!existing || mismatch || force) {
181
+ // Configure when there's nothing persisted yet, the persisted server.js
182
+ // path is stale (heal), an explicit --name/--group differs, or --force.
183
+ // Otherwise launch straight away — `start` stays cheap to run every
184
+ // session.
185
+ if (!existing || stale || mismatch || force) {
178
186
  const initArgs = ['init'];
179
187
  if (isProject) initArgs.push('--project');
180
188
  if (groupArg) initArgs.push('--group', groupArg);
189
+ // --force makes init honor the explicit --name/--group over the
190
+ // persisted value. Required on the rename path AND on stale-heal with
191
+ // an explicit --name, where init would otherwise preserve the old name
192
+ // and silently drop the request. Force alone never clobbers an
193
+ // unspecified group: resolveGroup() still preserves when no --group.
181
194
  if (existing && (mismatch || force)) initArgs.push('--force');
182
195
  const childEnv = Object.assign({}, process.env);
183
196
  if (nameArg) childEnv.SYM_NODE_NAME = nameArg;
@@ -188,7 +201,17 @@ if (cmd === 'start') {
188
201
  }
189
202
 
190
203
  console.log(`\n▶ Launching Claude Code on the SYM mesh — real-time push on.\n (channel: ${handle}; the dev flag is temporary until Anthropic allowlists it)\n`);
191
- const run = spawnSync('claude', claudeArgs, { stdio: 'inherit', cwd: launchDir });
204
+ // On Windows the `claude` CLI is a `.cmd`/`.ps1` shim (npm) or `.exe`
205
+ // (native installer). Node's spawn does an exact-filename lookup that
206
+ // ignores PATHEXT, so bare `spawnSync('claude', …)` returns ENOENT even
207
+ // when `claude` runs fine in the user's shell. Route through a shell on
208
+ // Windows so PATHEXT resolution kicks in; quote args that contain spaces
209
+ // since shell:true forwards the args unquoted.
210
+ const isWindows = process.platform === 'win32';
211
+ const spawnArgs = isWindows
212
+ ? claudeArgs.map((a) => (/\s/.test(a) ? `"${a}"` : a))
213
+ : claudeArgs;
214
+ const run = spawnSync('claude', spawnArgs, { stdio: 'inherit', cwd: launchDir, shell: isWindows });
192
215
  if (run.error && run.error.code === 'ENOENT') {
193
216
  process.stderr.write('ERROR: `claude` was not found on your PATH.\n');
194
217
  process.stderr.write('Install Claude Code (https://claude.com/code), make sure `claude` runs in your terminal, then re-run `sym-mesh-channel start`.\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sym-bot/mesh-channel",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "description": "MCP server — real-time agent-to-agent cognition for Claude Code remote teams via the SYM mesh.",
5
5
  "main": "server.js",
6
6
  "bin": {