Skip to content

fix(go/windows): root the default clone workspace under an absolute base#110

Merged
AbirAbbas merged 3 commits into
mainfrom
fix/107-windows-workspace-root
Jul 22, 2026
Merged

fix(go/windows): root the default clone workspace under an absolute base#110
AbirAbbas merged 3 commits into
mainfrom
fix/107-windows-workspace-root

Conversation

@AbirAbbas

Copy link
Copy Markdown
Collaborator

Fixes #107

Summary

On the Windows Go node, a build given only repo_url derived repo_path = /workspaces/<repo>-<buildID> — a drive-relative path with no drive letter. The node's os.MkdirAll and the spawned git resolve it from different contexts, and git clone fails in <60ms with "destination path … already exists and is not an empty directory" even though the freshly created directory is empty (git's is_empty_dir() also reports "not empty" when it can't open the directory).

Changes Made

Go node (primary fix):

  • New go/internal/workspace package: Root() resolves the workspace base — SWE_WORKSPACE_ROOT env override on every platform; %LOCALAPPDATA%\agentfield\workspaces on Windows (temp-dir fallback if LOCALAPPDATA is unset); byte-identical /workspaces everywhere else (Docker parity).
  • All three derivation sites use it (orch/build.go single- and multi-repo, orch/resolve.go, fast/build.go), keeping the existing <repo>-<buildID> / <repo>-resolve-<buildID> name patterns.
  • Hardening from the issue: clone destinations are no longer pre-created — only the parent dir is ensured and git clone creates the leaf itself, so the "already exists / not empty" refusal can't be triggered by the node's own mkdir. Applied to the initial clone, the reset-failed re-clone, and the resolve clone. The fast node's mkdir is intentionally untouched (it git-inits in place and needs the leaf).

Python node (same latent bug — it also runs on Windows):

  • _workspace_root() in swe_af/execution/schemas.py mirrors the exact resolution order (SWE_WORKSPACE_ROOT%LOCALAPPDATA%\agentfield\workspaces on os.name == "nt"/workspaces).
  • Same derivation-site wiring (app.py build/resolve, fast/app.py) and same parent-only mkdir hardening (single-repo clone, re-clone, resolve clone, multi-repo _clone_repos).

Explicitly provided repo_path values are used verbatim on all platforms, unchanged.

Testing

  • New table-driven tests for the root resolution on both sides (override, Windows + LOCALAPPDATA, Windows + neither, Linux default).
  • tests/test_build_isolation.py source-scraping assertions updated to the new derivation form (still guarding the issue-Agents in parallel builds appear to be getting cross-contaminated #43 build-scoped isolation contract).
  • Go: gofmt / go build / go vet / go test -race -count=1 ./... clean with GOWORK=off. Python: full suite 1134 passed, 1 pre-existing skip; compileall clean.

🤖 Generated with Claude Code

AbirAbbas and others added 3 commits July 22, 2026 15:21
…#107)

A build given only repo_url derived its clone target under a hardcoded
"/workspaces" base. On the Windows Go node that is a drive-relative path
(no drive letter), which the node's spawn context resolves unpredictably:
MkdirAll appears to succeed but `git clone` then fails with "destination
path ... already exists and is not an empty directory".

Add internal/workspace.Root(): SWE_WORKSPACE_ROOT override on every
platform, else %LOCALAPPDATA%\agentfield\workspaces on Windows (temp-dir
fallback when LOCALAPPDATA is empty), else exactly "/workspaces" for
Docker parity. Wire it into the three default-derivation sites (orch
build single/multi-repo, orch resolve, fast build) via filepath.Join so
the name/suffix patterns stay byte-identical.

Ref: #107

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
git clone refuses a destination it did not create with "already exists
and is not an empty directory" when it cannot re-open a node-created leaf
dir from the Windows spawn context. Pre-creating the clone target's leaf
therefore reintroduces the very failure issue #107 is about.

In the orch build and resolve clone paths (including the reset-failed
re-clone), create only filepath.Dir(repoPath) and let git clone create
the leaf. The fresh-init default case and the fast node keep creating the
leaf — they git-init in place rather than cloning.

Ref: #107

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Python node runs on Windows too and derived the same drive-relative
"/workspaces/..." defaults. Add _workspace_root() in execution/schemas.py
(SWE_WORKSPACE_ROOT override; else %LOCALAPPDATA%\agentfield\workspaces
on nt with a temp-dir fallback; else "/workspaces") and use it at every
default-derivation site: build single/multi-repo, resolve, and fast build.

Also stop pre-creating the clone destination leaf before git clone in the
single-repo, re-clone, resolve, and multi-repo clone_repos paths — create
only the parent so git clone owns the leaf, matching the Go node. Update
the build-isolation source assertions to the os.path.join form and add
_workspace_root unit tests (override, nt LOCALAPPDATA/tempdir, posix).

Ref: #107

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AbirAbbas
AbirAbbas merged commit 6dfc4e5 into main Jul 22, 2026
3 checks passed
@AbirAbbas
AbirAbbas deleted the fix/107-windows-workspace-root branch July 22, 2026 20:07
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.

bug(go/windows): default /workspaces/<repo>-<id> clone path fails — git reports fresh empty dir as 'not an empty directory'

1 participant