github mksglu/context-mode v1.0.119

latest release: v1.0.120
4 hours ago

v1.0.119 — community-driven release

A focused release closing 8 user-reported issues across 4 platforms (Pi, Cursor, Codex, Claude Code) and shipping a new architectural guardrail to prevent the v1.0.118 cascade from happening again. 4 PRs merged or extended, 1 closed-as-superseded with credit. All work is TDD-tested with vertical slices and reviewed independently by a parallel skeptic-architect pass.

What broke

#511Dynamic require of "node:fs" is not supported on Bun / Node 26 ESM

Three sites in the bundled MCP server still used inline require("node:..."). esbuild's ESM output rewrites these to a __require shim that throws under Bun 1.3 / Node 26. PR #513 (@Scotchy49) fixed the project-dir resolver. v1.0.119 sweeps the remaining sites in src/cli.ts:181 and src/adapters/qwen-code/index.ts:137, plus the buildFetchCode template literal whose require('node:dns') strings would have triggered the new bundle assertion.

#514 — Node 26 silently skipped better-sqlite3; /ctx-upgrade could not recover

better-sqlite3 lived in optionalDependencies. npm silently skips optional deps when the engine field excludes the host's Node version, and the heal script's package-missing branch was a no-op. This left users on Node 26 with no SessionDB and no automatic recovery path.

Fix: promoted to dependencies, made the heal script actively install with --no-optional --no-save, added a post-install binding verifier in cli.ts upgrade() that fails loud (non-zero exit) on absence, and split ctx_doctor's message so package-missing and binding-missing are distinct.

#516 — Pi adapter spawned a fork bomb on Bun-only Fedora 44

src/adapters/pi/mcp-bridge.ts:76 spawned process.execPath with [serverScript]. Inside the Pi extension host, process.execPath is the pi binary itself — every spawn started another full Pi instance, which loaded context-mode again, which spawned another Pi… exponential. Fatal when no Node was on PATH.

Fix: new resolveJsRuntimeForBridge() rejects pi-named binaries via case-insensitive basename regex (/^pi(\.exe)?$/i), falls back through detectRuntimes().javascript → PATH node/bun → graceful skip. Plus a CONTEXT_MODE_BRIDGE_DEPTH env counter that aborts if any future code path bypasses the binary check. 24/24 adversarial probes pass.

#517SAFE_COMMAND_PATTERNS rejected uname / id / realpath / ln

The PreToolUse Bash nudge fired ~85 tokens of context flooding for these benign commands. Added 4 anchored patterns mirroring the existing cp/mv/rm discipline (with -v/--verbose carve-out for ln). The existing SHELL_CONTROL_OPERATORS gate still trips first on any operator composition — verified across 13 attack vectors.

#518 — Same root as #511 (Windows + Bun)

Closed as duplicate of #511.

#519ctx_insight clarification

Closed as not-planned. The tool description, schema, and adapter docs all consistently say "open the dashboard". No live process introspection was ever advertised.

#520 — Scoped ctx_purge

Deferred to v1.0.120. Useful additive feature; sequencing it after the bug ship.

#521 — Cursor ctx_stats showed /

Two issues compounded: src/server.ts:213 hardcoded transcriptsRoot to ~/.claude/projects (Claude Code path) regardless of host, and src/util/project-dir.ts env candidate chain was missing CURSOR_CWD. Fix gates transcriptsRoot on detectPlatform().platform === "claude-code" and adds CURSOR_CWD as an additive escape hatch (Cursor itself does not appear to set this env on MCP child — verified via refs scan — so users currently need a manual ~/.cursor/mcp.json env override; documented).

#523/ctx-upgrade left stale Temp path in .claude-plugin/plugin.json

Sibling of #411. Where #411 fixed .mcp.json, #523 covers the other manifest. New HEAL Layer 5b in scripts/heal-installed-plugins.mjs (healPluginJsonMcpServers) wired into start.mjs, cli.ts upgrade(), and scripts/postinstall.mjs. Detects tmpdir-prefixed args[0] (regex matches both POSIX and Windows backslash forms), rewrites to ${CLAUDE_PLUGIN_ROOT}/start.mjs, asserts post-write or throws. 14 adversarial probes pass — path traversal guard, malformed JSON, symlink escape, sibling preservation, idempotence.

What's new

G3 — post-build bundle invariant assertion (scripts/assert-bundle.mjs)

A new architectural guardrail catches the #511 class of bug at build time before it reaches users. The script greps the bundle for Dynamic require of, __require\(['"]node:, and require(['"]node: patterns (single, double, and template-literal quotes, with whitespace tolerance). Wired into npm run build, the prepublishOnly chain, bundle.yml (blocks auto-commit on main), and ci.yml matrix (runs on Ubuntu + macOS + Windows).

withIsolatedEnv() — Windows test isolation helper (tests/util/isolated-env.ts)

Existing setup-home.ts only scoped HOME/USERPROFILE/HOMEDRIVE/HOMEPATH. Windows tests that touched adapter paths leaked through APPDATA/LOCALAPPDATA/XDG_*/TMPDIR. New helper covers all 13 keys plus deletes CLAUDE_PLUGIN_ROOT and CONTEXT_MODE_* overrides; mocks os.homedir() and os.tmpdir(). Refactored tests/statusline.test.ts and tests/statusline-sqlite.test.ts onto it. Cherry-picked the test contract that landed via @murataslan1's PR #515.

PR decisions

# Author Decision
#512 @tedjy971 MERGED + EXTENDED to next. Patched mcp.json shape (camelCase mcpServers + cwd: "." instead of the originally-suggested ${CODEX_PLUGIN_ROOT} — verified against refs/platforms/codex/codex-rs/core-plugins/src/loader.rs:1067-1075). Added .codex-plugin/* to version-sync.mjs targets.
#513 @Scotchy49 MERGED to next. Surgical ESM-safe project-dir fix with Bun + Node regression tests.
#515 @murataslan1 CLOSED as superseded. Test contract was incorporated into v1.0.119's broader Windows isolation work (commits bd5821a, a16c3dc). PR conflict against main was unresolvable cleanly; closing with credit and full attribution in this release.
#522 @mystilleef MERGED to next. Banner stderr suppression for Pi/MCP child output, with regression test.

Architectural defense in depth (cumulative v1.0.112 → v1.0.119)

The seven hotfixes 1.0.112→1.0.118 traced back to three architectural debts: (a) no single authoritative getProjectDir() boundary (4 of 7 hotfixes), (b) plugin-enabled state split across installed_plugins.json and settings.json, (c) no bundle-invariant CI gate. v1.0.119 closes (c) with G3 and tightens (a) by gating transcriptsRoot on platform; (b) was already covered by the v1.0.116 settings.json heal. Two architectural guardrails (G1 lint rule, G2 plugin-state SSoT) are documented for v1.0.120.

Tests

  • 2898 pass · 8 pre-existing baseline failures (tests/adapters/opencode.test.ts config-paths) — verified absent from v119 changeset, present on origin/next
  • 47 new TDD slices across the 8 fixes
  • 0 new regressions
  • Independent skeptic-architect review pass: 6 agents probed each fix with 5+ adversarial cases per scope; no blocking findings

Compatibility

15 adapters / 3 OS. Pi adapter on Bun-only Fedora 44 verified safe via CONTEXT_MODE_BRIDGE_DEPTH guard. Node 26 path now installs better-sqlite3 correctly via promoted dependency.

Upgrade

npm install -g context-mode@latest
# inside Claude Code:
/ctx-upgrade
# restart your session

If you were on a poisoned 1.0.118 install (plugin disconnected after upgrade, / shown in ctx_stats, fork bomb on Pi), the new HEAL Layer 5b in start.mjs repairs the manifest on next MCP boot. No manual cleanup required.

Thanks

Huge thanks to the community keeping context-mode honest this cycle.

First-time contributors @tedjy971, @Scotchy49, and @mystilleef shipped fixes spanning Codex marketplace exposure, ESM-safe project-dir resolution, and Pi banner suppression. @murataslan1 went deep on the Cursor ctx_stats regression and contributed the v1.0.118 statusline test contract that v1.0.119 builds on.

Thanks to @SkipXS, @marcinx64, @alaa-nassef, @rpickmans, @ollamabon-cmd, @zkzi3254, @tuanloc1105, and @acpatelmd for the high-signal repros across Pi, Cursor, Windows, and Node 26 — every one of you turned a vague breakage into a closeable bug. Reports with file:line citations and decoded Date.now() timestamps make this work possible.

Don't miss a new context-mode release

NewReleases is sending notifications on new releases.