Skip to content

[P0.27] OpenCode adapter writes outside the workspace — opencode ignores the subprocess cwd #1007

Description

@frankbria

Found while implementing #913 (PR pending). Distinct from that issue's contract, and worse than the bug it fixes.

Problem

Every SubprocessAdapter targets a task's workspace by passing cwd=workspace_path to subprocess.Popen. opencode does not honour it. It resolves its project directory from the parent process instead, so the delegated agent edits whatever directory CodeFRAME itself is running from.

Reproduction (opencode 1.18.7)

Running the binary-gated smoke test from the repo root:

# pytest process cwd = /home/frankbria/projects/codeframe
cmd = OpenCodeAdapter().build_command("Create a file named smoke.txt containing: works", repo)
subprocess.run(cmd, cwd=repo, ...)   # repo = a fresh tmp_path git repo

opencode reports success:

stdout: Created `smoke.txt` containing exactly `works` (5 bytes, no trailing newline).

and the file is not in repo. It is at /home/frankbria/projects/codeframe/smoke.txt — the pytest process's cwd. Reproduced twice (once via pytest, once via a standalone python3 -c harness with an explicit cwd=).

Why this is P0

Under codeframe serve, the parent cwd is the server's directory. A delegated task can therefore modify CodeFRAME's own checkout — or whatever directory the operator launched from — while the task's actual workspace is untouched.

require_file_changes (added in #913) does not catch it: that guard inspects the workspace for changes, finds none, and fails the run — correctly reporting failure while the edits have already landed somewhere else.

What I could not determine

opencode run --dir <workspace> looks like the intended remedy (--dir: "directory to run in"). Two attempts to verify it timed out at 240s and 280s and wrote nothing — but a plain opencode run timed out immediately afterwards too, so the timeouts track opencode instability today rather than --dir itself. I did not want to ship an unverified flag: an assumed-but-unverified CLI contract is exactly what caused #913.

Suggested approach

  1. Verify --dir against a responsive opencode; if it works, add it to OpenCodeAdapter.build_command alongside the existing cwd=.
  2. If --dir is not sufficient, check whether opencode honours an env var, or whether the adapter must chdir the child via preexec_fn/wrapper.
  3. Regression test: assert the file lands in the workspace when the parent process cwd is a different git repo — the exact discriminating condition. tests/core/adapters/test_opencode_smoke_913.py::test_the_adapter_command_actually_writes_a_file already xfails on this and becomes the test.

Evidence

  • codeframe/core/adapters/opencode.pybuild_command
  • codeframe/core/adapters/subprocess_adapter.py:110+ — where cwd= is passed
  • tests/core/adapters/test_opencode_smoke_913.py — the xfail marking this

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0-blocker-betaCritical blocker - must fix before beta testingbugSomething isn't workingpriority:high

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions