v1.0.114 — Hotfix: /ctx-upgrade no longer leaves the registry poisoned
A focused hotfix on top of v1.0.113. One bug class, three layers of defense.
What broke
After running /ctx-upgrade, Claude Code's installed_plugins.json could end up in an inconsistent state:
installPathpointed at the OLD version's cache directory (still on disk)versionfield claimed the NEW versionenabledPluginswas empty for context-mode
Claude Code's plugin loader rejected the mismatch and silently disconnected the MCP server. Symptom: /reload-plugins showed 0 plugins, every context-mode tool became unavailable, and the user had no in-product path back. The marketplace clone was also stuck at a stale version because the v1.0.108 pull fix could fail silently when the clone had drifted too far.
This affected every user who upgraded mid-session via /ctx-upgrade since the in-product upgrade flow shipped.
What changed
Defense-in-depth across three layers:
-
start.mjsHEAL 3 + HEAL 4 (self-recovery on every MCP boot). The newscripts/heal-installed-plugins.mjsshared module is invoked between the existing forward / reverse heals. HEAL 3 reads the installed plugin's actualplugin.jsonversion and rewrites the registryversionfield to match the truth on disk. HEAL 4 ensuresenabledPlugins["context-mode@context-mode"]carries the synced version. Both heals are idempotent and defensive (catch all errors, never block boot). -
scripts/postinstall.mjsself-heal (escape hatch for already-broken users). Whennpm install -g context-mode@1.0.114runs, postinstall fires the same heal logic against the user's~/.claude/plugins/installed_plugins.json. Critical for users whose plugin loader is rejecting context-mode entirely — start.mjs cannot help them because it never gets a chance to run. Postinstall also fires during Claude Code's own marketplace plugin install path (Claude Code runsnpm install --productionin the cache dir, triggering the hook). -
src/cli.ts upgradepre-bump and post-write assertions (root-cause prevention). Before bumping the registryversionfield, the upgrade flow now reads the target plugin'splugin.jsonand refuses to bump if versions disagree. After writing the registry, a consistency assertion verifiesinstallPathpoints to a directory whose manifest version matches the registryversion— throws loudly if not, so future bugs surface immediately instead of silently leaving the user broken. Marketplace pull also gets a post-pull version check that warns when the clone failed to advance to the expected version.
Tests
Three new test files, 31 new green tests:
tests/util/heal-installed-plugins.test.ts— 9 unit tests for the shared heal module (HEAL 3 version sync, HEAL 4 enabledPlugins create / rewrite / idempotent, no-registry skip, healthy no-op, path-traversal guard, native path separator, ships-in-files guard).tests/util/postinstall-heal.test.ts— 4 spawnSync integration tests against a staged npm-install layout (non-global skip, global heal, no-registry silent OK, already-healthy no-op).tests/util/cli-upgrade-verification.test.ts— 18 wiring-contract tests pinning the start.mjs imports, the layer ordering, the cli.ts pre/post-bump checks, and the bug-prevention contract.
Full suite: 2,810 pass, 8 baseline opencode failures (unrelated, present on origin/next baseline), 24 skipped, zero new regressions. Typecheck clean. Build clean.
Recovery for already-broken users
If you ran /ctx-upgrade on v1.0.113 and your plugin disappeared:
npm install -g context-mode@1.0.114
The npm postinstall hook will detect and heal the poisoned registry on the spot. Restart Claude Code; context-mode will reconnect.
If you cannot use npm, the start.mjs self-heal also fires on every MCP boot — but only if your plugin loader still allows context-mode to load. If it doesn't, the npm path above is the intended recovery.
Compatibility
15 adapters, 3 OS (macOS / Linux / Windows), no breaking changes, MCP surface unchanged. The heal logic uses node:path join only and was tested with both POSIX and Windows path separators.
Upgrade
ctx-upgrade # plugin (now safe)
npm install -g context-mode # standalone (also heals registry on install)
refs/ citations
refs/platforms/oh-my-pi/packages/coding-agent/test/marketplace/registry.test.ts:257-272— confirmedinstalled_plugins.jsonshaperefs/platforms/codex/codex-rs/app-server/src/config/external_agent_config_tests.rs:808— confirmedenabledPluginsmap shape