diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index fa2bc0f..501516f 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,14 +5,14 @@ }, "metadata": { "description": "Parallel Codex workers inside Claude Code.", - "version": "0.4.1" + "version": "0.4.2" }, "plugins": [ { "name": "magic-codex", "source": "./plugin", "description": "Parallel Codex workers inside Claude Code — multi-agent orchestration with git worktree isolation, resumable sessions, and dual-model PR review.", - "version": "0.4.1", + "version": "0.4.2", "author": { "name": "Wenqing Yu" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f6467a..94eafad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes documented here. Format follows [Keep a Changelog](https://keepachangelog.com/). +## [0.4.2] — 2026-04-27 + +Metadata-only release that fixes a release-process bug from 0.4.0 / 0.4.1. + +### Fixed +- **`plugin/.claude-plugin/plugin.json` was never bumped past `0.3.9`**, so Claude Code's plugin loader kept labeling the cache directory `0.3.9` even though the code on disk was the new release. Functionally invisible upgrades — `mtime` and code fingerprints (`demote` / `sandbox_denied` / `rate_limited`) confirmed the new behavior was active, but every diagnostic that read the plugin label reported the old version. Bumped to 0.4.2. +- **`src/mcp/codex-client.ts` MCP banner version** was also missed in the 0.4.1 commit (still said `0.4.0`). Bumped. + +### Added +- **Build-time version-drift guard** in `scripts/build.mjs`. The build now fails hard when `package.json`, `plugin/.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` (both the metadata and plugins[0] versions), or the two MCP banner literals disagree. Prevents this class of silent-mislabel bug from recurring. + ## [0.4.1] — 2026-04-27 This release closes the dispatcher-trust gap and adds a visibility surface for the workspace-write sandbox limitation that 0.4.0 only partially worked around. diff --git a/package.json b/package.json index 7aa6596..b821918 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magic-cc-codex-worker", - "version": "0.4.1", + "version": "0.4.2", "description": "Parallel Codex workers inside Claude Code — multi-agent orchestration.", "private": true, "license": "SEE LICENSE IN LICENSE", diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 999339c..2864fb3 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "magic-codex", - "version": "0.3.9", + "version": "0.4.2", "description": "Parallel Codex workers inside Claude Code — multi-agent orchestration with git worktree isolation, resumable sessions, and dual-model PR review.", "author": { "name": "Wenqing Yu", diff --git a/plugin/dist/index.js b/plugin/dist/index.js index 95acfe7..f581a20 100755 --- a/plugin/dist/index.js +++ b/plugin/dist/index.js @@ -27709,7 +27709,7 @@ var CodexChild = class { stderr: "pipe" }); this.client = new Client( - { name: "magic-codex", version: "0.4.0" }, + { name: "magic-codex", version: "0.4.2" }, { capabilities: {} } ); await this.client.connect(this.transport); @@ -28160,7 +28160,7 @@ async function main() { mfConventions }); const server = new Server( - { name: "magic-codex", version: "0.4.1" }, + { name: "magic-codex", version: "0.4.2" }, { capabilities: { tools: {} } } ); server.setRequestHandler(ListToolsRequestSchema, async () => ({ diff --git a/scripts/build.mjs b/scripts/build.mjs index ab46a74..e3bacd0 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -1,7 +1,47 @@ // Bundle src/index.ts into a single self-contained plugin/dist/index.js // that can run without node_modules at the install location. import { build } from "esbuild"; -import { rm, mkdir, cp, chmod } from "node:fs/promises"; +import { rm, mkdir, cp, chmod, readFile } from "node:fs/promises"; + +// Version-drift guard. We have five places where the version is +// duplicated, and missing one (most fatally `plugin/.claude-plugin/ +// plugin.json`, which is what Claude Code's plugin loader actually +// reads to decide what version to label the cache directory) makes a +// release functionally invisible — the runtime keeps loading the old +// label even though the code on disk is fresh. Fail the build hard +// when any literal disagrees with package.json's authoritative one. +const pkg = JSON.parse(await readFile("package.json", "utf8")); +const expected = pkg.version; +const versionedFiles = [ + { path: "plugin/.claude-plugin/plugin.json", get: (j) => j.version }, + { path: ".claude-plugin/marketplace.json", get: (j) => j.metadata.version }, + { + path: ".claude-plugin/marketplace.json", + get: (j) => j.plugins[0].version, + label: "marketplace.json plugins[0].version", + }, +]; +for (const v of versionedFiles) { + const json = JSON.parse(await readFile(v.path, "utf8")); + const actual = v.get(json); + if (actual !== expected) { + throw new Error( + `version drift: ${v.label ?? v.path} is "${actual}" but package.json says "${expected}". ` + + `Bump it before releasing — Claude Code's plugin loader reads ${v.path} to label the cache dir.`, + ); + } +} +// String-literal version refs in two MCP banners. cheap regex check. +for (const src of ["src/index.ts", "src/mcp/codex-client.ts"]) { + const text = await readFile(src, "utf8"); + const m = text.match(/name:\s*"magic-codex",\s*version:\s*"([^"]+)"/); + if (!m) continue; + if (m[1] !== expected) { + throw new Error( + `version drift: ${src} has "${m[1]}" but package.json says "${expected}".`, + ); + } +} await rm("plugin/dist", { recursive: true, force: true }); await mkdir("plugin/dist/roles", { recursive: true }); diff --git a/src/index.ts b/src/index.ts index a1d2d28..a2f62e0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -174,7 +174,7 @@ async function main() { }); const server = new Server( - { name: "magic-codex", version: "0.4.1" }, + { name: "magic-codex", version: "0.4.2" }, { capabilities: { tools: {} } }, ); diff --git a/src/mcp/codex-client.ts b/src/mcp/codex-client.ts index 7ea92f1..b63e0f7 100644 --- a/src/mcp/codex-client.ts +++ b/src/mcp/codex-client.ts @@ -52,7 +52,7 @@ export class CodexChild { stderr: "pipe", }); this.client = new Client( - { name: "magic-codex", version: "0.4.0" }, + { name: "magic-codex", version: "0.4.2" }, { capabilities: {} }, ); await this.client.connect(this.transport);