#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.
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.
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.