From 41f25f8fbadacae8668e63011ae66e8138adae13 Mon Sep 17 00:00:00 2001 From: geobelsky Date: Thu, 11 Jun 2026 12:40:44 +0000 Subject: [PATCH] release: CLI v0.6.1 + extension v0.1.6 + plugin manifest catch-up Launch-readiness release carrying the fixes from the core and extension launch-readiness PRs. Bumps, this time following scripts/release.sh conventions (the v0.6.0 release bypassed it, which is how plugin.json drifted): package.json 0.6.0 -> 0.6.1 extension/package.json 0.1.5 -> 0.1.6 .claude-plugin/plugin.json 0.5.0 -> 0.6.1 (catch-up: skipped in v0.6.0) templates/plugin-README.md badge 0.5.0 -> 0.6.1 Plus release-process guards so the June-3 incidents cannot recur silently: - release-binary.yml: fail before building when tag / package.json / plugin.json versions disagree. - publish-extension.yml: same for extension/package.json. - release.sh postflight: verify the anthropics/claude-plugins-community SHA pin matches the plugin repo HEAD, with exact bump-PR instructions when it doesn't (the pin had silently pointed at April's v0.2.9 through three releases). Co-Authored-By: Claude Opus 4.8 --- .claude-plugin/plugin.json | 2 +- .github/workflows/publish-extension.yml | 16 +++++++++++++ .github/workflows/release-binary.yml | 18 ++++++++++++++ CHANGELOG.md | 23 ++++++++++++++++++ extension/package.json | 2 +- package.json | 2 +- scripts/release.sh | 31 ++++++++++++++++++++++++- templates/plugin-README.md | 2 +- 8 files changed, 91 insertions(+), 5 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 4a167ad..2e90223 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "axme-code", - "version": "0.5.0", + "version": "0.6.1", "description": "(Alpha) Persistent memory, architectural decisions, and safety guardrails for Claude Code. Your agent starts every session with full project context — stack, decisions, patterns, safety rules, and a handoff from the previous session.", "author": { "name": "AXME AI", diff --git a/.github/workflows/publish-extension.yml b/.github/workflows/publish-extension.yml index b5205ef..92d862f 100644 --- a/.github/workflows/publish-extension.yml +++ b/.github/workflows/publish-extension.yml @@ -52,6 +52,22 @@ jobs: steps: - uses: actions/checkout@v4 + # Guard against tag/manifest drift (same class as the v0.6.0 incident: + # extension-v0.1.5 was first tagged before the version-bump PR merged, + # so the workflow built a 0.1.4-manifest .vsix and Open VSX rejected it + # as already published). Fail before building. + - name: Verify tag matches extension manifest + if: startsWith(github.ref, 'refs/tags/extension-v') + shell: bash + run: | + tag="${GITHUB_REF#refs/tags/extension-v}" + ver="$(jq -r .version extension/package.json)" + if [ "$tag" != "$ver" ]; then + echo "::error::Version drift: tag extension-v${tag} vs extension/package.json ${ver}. Merge the release PR before pushing the tag, then re-tag on the merged commit." + exit 1 + fi + echo "Extension manifest consistent: extension-v${tag}" + - uses: actions/setup-node@v4 with: node-version: 20 diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index e54cab4..b99f00d 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -42,6 +42,24 @@ jobs: - name: Checkout uses: actions/checkout@v4 + # Guard against tag/manifest drift. June 2026 postmortem: the v0.6.0 + # tag was pushed before the release PR merged (binaries said 0.6.0, + # package.json said 0.5.0), and .claude-plugin/plugin.json was not + # bumped at all for two releases — Claude Code keys plugin update + # detection on that version, so plugin users were stuck. Fail the + # whole release BEFORE building anything if the three disagree. + - name: Verify tag matches version manifests + if: startsWith(github.ref, 'refs/tags/v') + run: | + tag="${GITHUB_REF#refs/tags/v}" + pkg="$(jq -r .version package.json)" + plugin="$(jq -r .version .claude-plugin/plugin.json)" + if [ "$tag" != "$pkg" ] || [ "$tag" != "$plugin" ]; then + echo "::error::Version drift: tag v${tag} vs package.json ${pkg} vs .claude-plugin/plugin.json ${plugin}. Merge the release PR (which bumps all manifests in lockstep) BEFORE pushing the tag, then re-tag on the merged commit." + exit 1 + fi + echo "Version manifests consistent: v${tag}" + - name: Setup Node uses: actions/setup-node@v4 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 98f3e39..864f198 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ ## [Unreleased] +## [0.6.1] - 2026-06-11 + +Launch-readiness release. A four-agent audit of every distribution channel (standalone binary, npm, Claude Code plugin, Cursor extension) — with findings reproduced against the released v0.6.0 / extension-v0.1.5 artifacts — surfaced a set of first-run and channel-health bugs. This release fixes all of them and adds release-process guards so the channel breakages cannot silently recur. + +### Fixed + +- **Plugin audit pipeline was dead for plugin installs.** The detached audit-worker spawner reused `process.argv[1]`, which for plugin installs is `server.mjs` (no CLI dispatch) — finalize-close, disconnect cleanup, and orphan recovery booted a second MCP server that exited immediately instead of running the audit. Sessions were never audited and orphan recovery re-queued them forever. The spawner now resolves the sibling `cli.mjs` when argv[1] is a server entry. +- **Auto-update silently disabled for all binary installs.** `fetchLatestRelease()` used `/releases/latest`, which resolves to whichever release was published most recently — currently `extension-v0.1.5` — so the semver comparison hit NaN and no update ever happened. Same bug class as the install.sh 404 fixed in v0.6.0; same fix (release-list endpoint filtered to `^v[0-9]`). +- **`axme-code setup --help` ran a full paid LLM scan into a literal `--help/` directory.** Unknown flags fell through to the positional-path slot (reproduced: $0.49 and $0.77 of API spend). Setup now rejects unknown flags (exit 2), prints usage for `--help`/`-h`, rejects nonexistent paths, and rejects extra positionals. +- **Setup destroyed user config when a JSON file was hand-edited.** Invalid JSON in `.claude/settings.json`, `.mcp.json`, `.cursor/mcp.json`, or `.cursor/hooks.json` hit a `catch { … = {} }` fallback and the file was silently rewritten — wiping the user's permissions, env, other MCP servers, and their own hooks. All writers (CLI and extension) now refuse with an actionable error and leave the file untouched. +- **Interrupted setup permanently bricked setup.** `setup.lock` removal was skipped on any scanner exception; `--force` didn't bypass the lock; the rerun printed a misleading "Already initialized … Done!" (exit 0). The lock is now held in try/finally, self-expires after 15 minutes, `--force` bypasses it, and a genuine lock-skip reports honestly (exit 1 with recovery instructions). +- **First-run setup created duplicate decision IDs.** Preset bundles and the init scanner both numbered from D-001, so D-001..D-009 were written twice and every later lookup/supersede by id was ambiguous. `saveDecisions` now renumbers colliding ids past the max stored id (including superseded ones). +- **Cursor extension (Windows): hooks duplicated on every restart and could not be removed.** The dedupe/uninstall filter matched only `axme-code`, but Windows hook commands reference `axme-hook.cmd` — every activation appended three more entries, and Reset/uninstall left them behind pointing at a deleted wrapper. The filter now matches both shapes; with it fixed, the per-activation rewrite also self-heals stale version-dir paths after extension updates. +- **Cursor extension (macOS/Linux): Node-less machines got an unexplained dead extension.** The bundled CLI is a `#!/usr/bin/env node` shim and Cursor spawns the MCP server outside the extension host — without Node 20+ on PATH users saw "MCP server does not exist" and silently failing hooks. New soft-fail activation preflight surfaces an actionable error (with an Open-nodejs.org button) and a `Node` line in the activation report. install.sh now performs the same check at install time (`AXME_SKIP_NODE_CHECK=1` to bypass), and the README documents the Node 20+ requirement for Linux/macOS. +- **Extension-spawned setup wrote duplicate/stale project-level Cursor config.** `setup --ide cursor` wrote `.cursor/mcp.json` (a same-name `axme` server with a PATH-dependent command that extension-only users can't run) and `.cursor/hooks.json` (absolute paths into the version-numbered extension dir — stale after every update, double-firing on top of user-level hooks). The extension now passes `AXME_SETUP_FROM_EXTENSION=1` and the CLI skips both writers under it. +- **Contradictory "not initialized" instructions.** The server instructions said "EXECUTE inline setup", `axme_context` said "do NOT run setup", and the plugin-written CLAUDE.md said "run `axme-code setup --plugin` via Bash immediately" (impossible for plugin installs — the binary is not on PATH). All surfaces now tell one story: offer the user setup, on consent execute the inline `axme_save_*` flow; never invoke `axme-code` via Bash. Also removed the "runs inline on your Cursor subscription" wording shown to Claude Code users, fixed `axme_status`'s reference to the long-removed `axme_init`, and the hooks summary line now mentions PreToolUse. +- **MCP `serverInfo.version` was hardcoded `0.1.0`.** Now reports the real release version. +- **`.claude-plugin/plugin.json` version catch-up (0.5.0 → 0.6.1).** The v0.6.0 release was prepared manually, bypassing `scripts/release.sh`, so the plugin manifest (and the plugin README badge) stayed at 0.5.0 — and Claude Code keys plugin update detection on that version. + +### Added + +- **Release-process guards.** `release-binary.yml` fails before building if the tag, `package.json`, and `.claude-plugin/plugin.json` versions disagree; `publish-extension.yml` does the same for `extension/package.json`. Either guard would have caught both June-3 release incidents (tag pushed before the release PR merged; plugin manifest drift). `scripts/release.sh` postflight now also verifies the **community-marketplace SHA pin** — `claude plugin install axme-code@claude-community` installs the commit pinned in `anthropics/claude-plugins-community`, not our plugin repo HEAD, and that pin still pointed at April's v0.2.9 until this release cycle. The check prints exact instructions for the marketplace bump PR until it lands. + ## [0.6.0] - 2026-06-03 A multi-IDE / multi-host release. Adds first-class Cursor support (hook adapter, transcript parser, AgentSdk factory), upgrades telemetry attribution for setup failures, fixes a long-standing pile of search-mode-on-Windows installation issues, hardens the scanners against credential reads, and makes the `axme_finalize_close` schema produce actionable errors when an agent omits a required field. diff --git a/extension/package.json b/extension/package.json index ca36b17..c50e2fc 100644 --- a/extension/package.json +++ b/extension/package.json @@ -2,7 +2,7 @@ "name": "axme-code", "displayName": "AXME Code", "description": "Persistent memory, decisions, and safety guardrails for Cursor, GitHub Copilot, Cline, Continue, Roo Code, Windsurf, and VS Code chat agents", - "version": "0.1.5", + "version": "0.1.6", "publisher": "AxmeAI", "repository": { "type": "git", diff --git a/package.json b/package.json index b32982f..328f044 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@axme/code", - "version": "0.6.0", + "version": "0.6.1", "description": "Persistent memory, decisions, and safety guardrails for Claude Code", "type": "module", "main": "./dist/server.js", diff --git a/scripts/release.sh b/scripts/release.sh index 7e578cc..75d4cbd 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -14,7 +14,18 @@ # 3. Open release PR (release/vX.Y.Z), commit "release: bump version to X.Y.Z" # 4. Wait for user to merge the PR (script pauses) # 5. After merge: tag, push, watch chained workflow (build → release → npm → plugin sync) -# 6. Postflight verify: npm version, GitHub release, plugin repo plugin.json +# 6. Postflight verify: npm version, GitHub release, plugin repo plugin.json, +# AND the community-marketplace SHA pin (see below) +# +# IMPORTANT — the Claude Code marketplace pins us by SHA: +# `claude plugin install axme-code@claude-community` reads +# anthropics/claude-plugins-community/.claude-plugin/marketplace.json, +# which pins our plugin to a COMMIT SHA of AxmeAI/axme-code-plugin. Our +# sync job updates the plugin repo, but new users keep getting the pinned +# SHA until someone opens a PR to claude-plugins-community bumping it. +# (Discovered 2026-06-11: the pin still pointed at v0.2.9 from April — +# every release since had been invisible to plugin installers.) The +# postflight check below fails loudly until the marketplace PR lands. # # Why this exists: # The v0.2.7 release took ~5 retries because of drift between manual steps: @@ -422,6 +433,24 @@ else err " Check the workflow run logs for sync-plugin-repo job" fi +# 4. Community marketplace SHA pin — the part of the chain we do NOT own. +# `claude plugin install axme-code@claude-community` installs the commit +# pinned in anthropics/claude-plugins-community, NOT our plugin repo HEAD. +# Without a marketplace PR every release is invisible to new plugin users. +echo " checking anthropics/claude-plugins-community SHA pin..." +plugin_head="$(gh api "repos/${PLUGIN_REPO}/commits/main" --jq '.sha' 2>/dev/null || echo "FETCH_FAILED")" +pinned_sha="$(curl -fsSL "https://raw.githubusercontent.com/anthropics/claude-plugins-community/main/.claude-plugin/marketplace.json" 2>/dev/null \ + | jq -r '.plugins[] | select(.name == "axme-code") | .source.sha' 2>/dev/null || echo "FETCH_FAILED")" +if [ "$pinned_sha" = "$plugin_head" ] && [ "$pinned_sha" != "FETCH_FAILED" ]; then + ok "marketplace pin is current ($pinned_sha)" +else + err "marketplace pins $pinned_sha but $PLUGIN_REPO main is $plugin_head" + err " New plugin installs will keep getting the OLD version until this lands:" + err " 1. Fork anthropics/claude-plugins-community" + err " 2. In .claude-plugin/marketplace.json set axme-code .source.sha = $plugin_head" + err " 3. Open a PR (their CI + maintainers review it)" +fi + # --- Done --- step "Release ${new_tag} complete" diff --git a/templates/plugin-README.md b/templates/plugin-README.md index 18b8775..9b11ca7 100644 --- a/templates/plugin-README.md +++ b/templates/plugin-README.md @@ -5,7 +5,7 @@ Persistent memory, architectural decisions, and safety guardrails for Claude Code. Your agent starts every session with full project context — stack, decisions, patterns, safety rules, and a handoff from the previous session. [![Alpha](https://img.shields.io/badge/status-alpha-orange)]() -[![Version](https://img.shields.io/badge/version-0.5.0-blue)]() +[![Version](https://img.shields.io/badge/version-0.6.1-blue)]() [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE) **[Main Repository](https://github.com/AxmeAI/axme-code)** · **[Website](https://code.axme.ai)** · **[Issues](https://github.com/AxmeAI/axme-code/issues)**