3 Commits

Author SHA1 Message Date
Mert Koseoglu 89f4e73630 fix(sandbox): suppress MinGW path-conv for Windows ctx_execute child (#782) + clean .ctx-mode-* temp + pin cwd (#788)
#782: On Windows Git Bash, a bare `mvn` runs Maven's POSIX script which on
the mingw branch leaves CLASSWORLDS_JAR as a POSIX path that native java.exe
cannot resolve (ClassNotFoundException). Rewrite the bare `mvn` token to
`mvn.cmd` (native Windows launcher) in shell scripts. This avoids re-enabling
global MSYS path-conversion suppression that #826/#791 removed for native git.

#788(a): Non-shell runtimes (python/js/ts/...) ran with cwd=sandbox tmpDir, so
repo-relative checks failed depending on language. Unify cwd to the project
root (or per-call override) for all languages; the script file still lives in
the sandbox and is passed by absolute path.

#788(b): .ctx-mode-* temp dirs leaked on Windows when SQLite -wal/-shm handles
lingered and a single rmSync threw EBUSY/EPERM into a silent catch. Add
cleanupTmpDir() with rmSync maxRetries/retryDelay backoff.
2026-06-21 18:36:47 +03:00
Mert Koseoglu dd8477cf06 fix(test): cross-platform cwd assertions in cwd-override
Windows CI failed because the test used `pwd` (shell-builtin) and
compared its output to `mkdtempSync` output. On Git Bash/MSYS,
`pwd` translates `C:\Users\RUNNER~1\...\Temp\xxx` to `/tmp/xxx`,
which never matches the JS-side Windows path.

Switch to `node -p "process.cwd()"` so cwd is printed by Node
itself (no MSYS translation), and normalize both sides via
`realpathSync` to canonicalize Windows 8.3 short names
(`RUNNER~1` → `runneradmin`) and macOS `/var` → `/private/var`.
Compare case-insensitively on Windows/macOS where the filesystem is.
2026-05-24 20:31:05 +03:00
Mert Koseoglu a12a64c28e fix(server): recover project cwd from Codex session log (#45)
Codex CLI publishes no workspace env var to its MCP child, so when the
host is launched from outside a project (e.g. $HOME), every project-aware
tool (ctx_stats, SessionDB, hash) ends up rooted at $HOME instead of the
user's project. Mirror Claude Code's transcript heuristic for Codex:

  * resolveCodexSessionCwd() — read meta.cwd from the most-recently-
    modified ${CODEX_HOME ?? ~/.codex}/sessions/<uuid>.jsonl; with
    plugin-install-path poison guard and transcriptMaxAgeMs freshness
    gate (multi-window safety).
  * resolveProjectDir() — when strictPlatform === "codex" and the env
    cascade yields nothing, fall through to the session-log heuristic
    BEFORE PWD/cwd.
  * src/server.ts getProjectDir() — when detectPlatform() returns
    "codex", pass codexHome to the resolver so production code reaches
    the new branch (without this wiring it was dead code). Export
    getProjectDir for integration testing.
  * PolyglotExecutor — accept an explicit cwd override on ExecuteOptions
    so per-call sites can pin shell cwd to the resolved project root
    without mutating process-wide state.

Tests:
  * tests/util/codex-session-cwd-resolution.test.ts — 15 unit tests on
    the helper + resolveProjectDir strict-codex branch (fresh log wins,
    stale rejected, malformed survived, plugin path poison rejected,
    missing sessions dir handled, foreign env ignored).
  * tests/executor/cwd-override.test.ts — 2 tests proving the
    PolyglotExecutor cwd override pins shell pwd and falls back to
    projectRoot when undefined.
  * tests/integration/project-dir-strict.test.ts — extended with an
    end-to-end test that boots getProjectDir() in a Codex-shaped env
    (CODEX_THREAD_ID + CODEX_HOME pointing at a fresh fixture session)
    and asserts the returned path is the session-log meta.cwd. Verifies
    the full #45 chain: detector -> server.getProjectDir() -> resolver
    -> session log -> meta.cwd.
  * .mcp.json.codex.example — Codex-specific manifest snippet
    documenting CONTEXT_MODE_PROJECT_DIR as the explicit escape hatch.

All 209 tests in tests/util/, tests/integration/, tests/executor/ pass.
tsc --noEmit clean.
2026-05-24 19:07:30 +03:00