Skip to content

fix: provider-cli pick spawns anchor at the sandbox project (real-repo config corruption) - #138

Merged
pacphi merged 1 commit into
mainfrom
fix/provider-cli-cwd-leak
Aug 12, 2026
Merged

fix: provider-cli pick spawns anchor at the sandbox project (real-repo config corruption)#138
pacphi merged 1 commit into
mainfrom
fix/provider-cli-cwd-leak

Conversation

@pacphi

@pacphi pacphi commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Fixes #137.

The leak

akPick() destructures { cwd, home, binDir, catalog } but pickSandbox() returns { home, project, binDir, catalog } — all 20 call sites pass the sandbox object wholesale, so cwd was always undefined and spawnSync inherited the test process's cwd: the real repository root. HOME/XDG/APPDATA were correctly sandboxed (kit.json and ~/.claude were safe), but ak x host pick --yes also performs PROJECT-scoped writes anchored at repoRoot(cwd):

  • .claude/settings.local.jsonENABLE_CODEX: "false" from claude-only fixtures
  • .agentic-qe/llm-config.json → fixture claude-code→openai chain, empty agentOverrides

Every pnpm test / pnpm run check on a developer machine silently regressed that machine's real provider/routing state. Two properties kept it invisible: rewrites are idempotent (an already-corrupted repo shows no mtime-content change on reruns), and CI runs in a throwaway checkout. This retroactively explains recurring "mysterious" post-test-run drift on a dev machine that ak sync kept re-healing.

The fix

  1. akPick anchors the spawn at the sandbox project: cwd: cwd ?? project (heals all 20 call sites).
  2. A tripwire after() hook records the real cwd's two project files at module load and asserts them byte-identical when the suite ends — any future harness regression of this class fails the suite loudly instead of corrupting machines silently.

Verification

  • TDD: tripwire added first; from a healthy repo state it fired on settings.local.json before the anchor fix (the corrupted state had masked it — idempotent rewrites — so the repo was healed first to expose true RED).
  • After the fix: suite green (18 tests incl. tripwire), and a full pnpm run check (1469 tests, 0 fail) leaves both real files hash-identical (md5 before/after).

🤖 Generated with Claude Code

…al-repo tripwire

akPick() destructured { cwd, ... } but pickSandbox() returns { project, ... },
so every call site spawned `ak x host pick --yes` with cwd undefined —
inherited from the test process: the real repository root. HOME/XDG/APPDATA
were correctly sandboxed, but pick's PROJECT-scoped writes anchor at
repoRoot(cwd), so each full test run rewrote the developer's real
.claude/settings.local.json (ENABLE_CODEX=false) and
.agentic-qe/llm-config.json (fixture openai chain, empty overrides).
Idempotent rewrites kept the corruption invisible on an already-hit repo,
and CI's throwaway checkout never surfaced it.

The spawn now anchors at cwd ?? project, and an after() tripwire records
the real cwd's two project files at module load and asserts them
byte-identical when the suite ends — a future harness regression fails
loudly instead of corrupting machines silently. Verified: from a healthy
repo state the tripwire fired before the anchor fix, and a full
pnpm run check now leaves both files hash-identical.

Fixes #137
@pacphi
pacphi merged commit b2ea316 into main Aug 12, 2026
11 checks passed
@pacphi
pacphi deleted the fix/provider-cli-cwd-leak branch August 12, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: provider-cli tests spawn 'ak x host pick' with cwd undefined, corrupting the developer's real project config

1 participant