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
- Verify
--dir against a responsive opencode; if it works, add it to OpenCodeAdapter.build_command alongside the existing cwd=.
- If
--dir is not sufficient, check whether opencode honours an env var, or whether the adapter must chdir the child via preexec_fn/wrapper.
- 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.py — build_command
codeframe/core/adapters/subprocess_adapter.py:110+ — where cwd= is passed
tests/core/adapters/test_opencode_smoke_913.py — the xfail marking this
Found while implementing #913 (PR pending). Distinct from that issue's contract, and worse than the bug it fixes.
Problem
Every
SubprocessAdaptertargets a task's workspace by passingcwd=workspace_pathtosubprocess.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:
opencode reports success:
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 standalonepython3 -charness with an explicitcwd=).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 plainopencode runtimed out immediately afterwards too, so the timeouts track opencode instability today rather than--diritself. I did not want to ship an unverified flag: an assumed-but-unverified CLI contract is exactly what caused #913.Suggested approach
--diragainst a responsive opencode; if it works, add it toOpenCodeAdapter.build_commandalongside the existingcwd=.--diris not sufficient, check whether opencode honours an env var, or whether the adapter mustchdirthe child viapreexec_fn/wrapper.tests/core/adapters/test_opencode_smoke_913.py::test_the_adapter_command_actually_writes_a_filealready xfails on this and becomes the test.Evidence
codeframe/core/adapters/opencode.py—build_commandcodeframe/core/adapters/subprocess_adapter.py:110+— wherecwd=is passedtests/core/adapters/test_opencode_smoke_913.py— the xfail marking this