From 523a5ebf3a4c07c15b5ac6c5f0498e306ebef893 Mon Sep 17 00:00:00 2001 From: Evan Nadeau <1878498+evannadeau@users.noreply.github.com> Date: Fri, 15 May 2026 12:51:43 -0700 Subject: [PATCH] fix(orchestrator): version-drift + path-hashing leading-dash strip in mcp/server.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two trivial fixes in mcp/server.ts plus rebuilt dist/server.js (bun build, 249 modules; 516/516 tests pass). 1. Version-drift (mcp/server.ts:655) `system_status` reported a hardcoded `0.30.28` instead of the dynamically-read `${PLUGIN_VERSION}` (set from package.json at module load, lines 32-37). The 0.30.31 consolidation that introduced PLUGIN_VERSION explicitly aimed to fix this kind of drift but missed this one site. Symptom: every release since (0.30.32 → 0.30.38) has shipped `system_status` reporting `0.30.28`. 2. Path-hashing leading-dash strip (mcp/server.ts:2184) `projectHash` stripped leading dashes after replacing path separators: projectDir.replace(/[\\/:]/g, "-").replace(/^-+/, ""); On POSIX, every absolute path produces a leading dash after the replace, which the strip then removes. But Claude Code preserves the leading dash when it names project directories under `~/.claude/projects/-<...>`. The mismatch silently breaks the agent-channel filewatcher: `projectsHashDir` resolves to a non-existent directory, `listJsonlFiles()` returns `[]`, and every `@SA-` channel address gets silently dropped. Symlinking the stripped name to the real one restores routing (validated workaround); the proper fix is to stop stripping. On Windows, the prior leading-dash strip was over-correction for the drive-letter case (`C:\foo` → `C--foo`) — a cosmetic double-dash, not broken routing. Removing the strip is harmless there. dist/server.js regenerated via `bun run build` against the same source to guarantee the bundled artifact matches the source (per the long-stale PR rebuild-after-rebase rule). --- plugins/orchestrator/dist/server.js | 4 ++-- plugins/orchestrator/mcp/server.ts | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/orchestrator/dist/server.js b/plugins/orchestrator/dist/server.js index 6b6141f..a238a58 100644 --- a/plugins/orchestrator/dist/server.js +++ b/plugins/orchestrator/dist/server.js @@ -24819,7 +24819,7 @@ server.tool("system_status", "Check the health of the orchestrator system: embed const lines = []; lines.push("## System Status"); lines.push(""); - lines.push(`- **Version**: orchestrator MCP server **0.30.28** (pid ${process.pid})`); + lines.push(`- **Version**: orchestrator MCP server **${PLUGIN_VERSION}** (pid ${process.pid})`); if (agentChannel) { lines.push(`- **Agent-channel**: ACTIVE - filewatcher running`); } else { @@ -26044,7 +26044,7 @@ function startAgentChannel() { `); return; } - const projectHash = projectDir.replace(/[\\/:]/g, "-").replace(/^-+/, ""); + const projectHash = projectDir.replace(/[\\/:]/g, "-"); const projectsHashDir = join5(homedir2(), ".claude", "projects", projectHash); const roleEnv = process.env.ORCHESTRATOR_AGENT_ROLE ?? process.env.SPAWNBOX_AGENT_ROLE; const role = roleEnv === "prime" ? "prime" : "subordinate"; diff --git a/plugins/orchestrator/mcp/server.ts b/plugins/orchestrator/mcp/server.ts index 85eed16..3ab1828 100644 --- a/plugins/orchestrator/mcp/server.ts +++ b/plugins/orchestrator/mcp/server.ts @@ -652,7 +652,7 @@ server.tool( const lines: string[] = []; lines.push("## System Status"); lines.push(""); - lines.push(`- **Version**: orchestrator MCP server **0.30.28** (pid ${process.pid})`); + lines.push(`- **Version**: orchestrator MCP server **${PLUGIN_VERSION}** (pid ${process.pid})`); if (agentChannel) { lines.push(`- **Agent-channel**: ACTIVE - filewatcher running`); } else { @@ -2181,7 +2181,10 @@ function startAgentChannel(): void { // Project hash dir under ~/.claude/projects/. Hash mirrors how Claude Code // names the per-project directory: replace path separators + drive colons // with hyphens, leading hyphens trimmed. - const projectHash = projectDir.replace(/[\\/:]/g, "-").replace(/^-+/, ""); + // Hash the project directory the same way Claude Code does: replace path separators + // and colons with dashes, preserving any leading dash (POSIX absolute paths produce + // a leading "-home-..." form, and CC keeps the leading dash in ~/.claude/projects/). + const projectHash = projectDir.replace(/[\\/:]/g, "-"); const projectsHashDir = join(homedir(), ".claude", "projects", projectHash); // Role/name env vars: ORCHESTRATOR_AGENT_* is the canonical form (set by