Skip to content

fix(acp): emit [Workspace] section for Windows drive-letter cwd - #3130

Open
kcao-gss wants to merge 1 commit into
block:mainfrom
kcao-gss:fix/workspace-section-absolute-path
Open

fix(acp): emit [Workspace] section for Windows drive-letter cwd#3130
kcao-gss wants to merge 1 commit into
block:mainfrom
kcao-gss:fix/workspace-section-absolute-path

Conversation

@kcao-gss

Copy link
Copy Markdown
Contributor

Summary

workspace_section() gated the [Workspace] system-prompt block on cwd.starts_with('/'), so it was silently dropped for every Windows agent — cwd comes from std::env::current_dir() (lib.rs:1547-1550), which on Windows is always drive-letter form (C:\Users\<user>\.buzz).

Replaces the string-prefix test with Path::is_absolute() && Path::parent().is_some(), which preserves both invariants the original guard existed for — reject relative paths, reject the / sentinel current_dir() falls back to on failure — and generalizes the second to reject C:\, \\?\C:\, and UNC share roots uniformly.

Fixes #3124

Scope, stated honestly

This is not "Windows agents don't know about their workspace." base_prompt.md:84-100 already ships the Workspace Layout table (REPOS/, OUTBOX/) and the "never run find over $HOME" instruction unconditionally on every platform, and the agent's OS cwd is the workspace (the child inherits it). What Windows was missing is the absolute-path anchor — one reinforcing sentence. Filed and fixed as a correctness bug, not a user-facing breakage.

Why the platform-dependent predicate is deliberate

Path::is_absolute is platform-dependent, and that is correct here rather than a hazard: cwd only ever originates from current_dir() in the same process on the same host, so the compile-time platform always matches the path's dialect. Audited — PromptContext (pool.rs:482) has no derives (so no deserialization path), its only production constructor is lib.rs:1530, no crate outside buzz-acp references it, and there is no CLI flag or env override for cwd. The reasoning is now recorded in the function's doc comment so a future maintainer doesn't "fix" it back to a string prefix test.

Deliberately not done: normalizing the cwd string upstream. The same string is the ACP session/new cwd (pool.rs:831), so rewriting it would change protocol behavior for every harness.

Tests

  • #[cfg(windows)]: drive-letter cwd → Some; C:\None.
  • #[cfg(unix)]: /Users/me/.buzzSome.
  • Ungated (platform-neutral): /None, relative/pathNone, ""None.

Two POSIX-path assertions needed #[cfg(unix)] gating as a direct consequence of this change — including the pre-existing test_framed_system_prompt_absolute_cwd_prepends_workspace_before_base, which was green on Windows before, because Path::new("/Users/me/.buzz").is_absolute() is false on Windows (root, no drive prefix). Called out explicitly since it's the one non-obvious side effect of the fix.

Reviewer note: the #[cfg(windows)] tests do not currently execute in CI. .github/workflows/ci.yml:945-947 runs cargo clippy and cargo check --workspace --all-targets on windows-latest (so they compile), but the only Windows cargo test invocations are -p buzz-dev-mcp (:953) and the Tauri crate (:988). Adding -p buzz-acp to that step would make them enforcing — happy to include it here if you want it, or leave it separate.

Test plan

  • cargo test -p buzz-acp workspace_section — 3 passed
  • cargo test -p buzz-acp framed_system_prompt — 7 passed
  • cargo fmt --check -p buzz-acp — clean
  • cargo clippy -p buzz-acp — clean
  • cargo test -p buzz-acp on a Windows target (no Windows host available to me — this is the one gap, and it's exactly what the two #[cfg(windows)] tests are for)

Out of scope, noted for follow-up

Now that Windows agents receive this text:

  • The section says "do not search $HOME" — POSIX phrasing that reads oddly on Windows (base_prompt.md:100 has the same issue).
  • {cwd}/REPOS/ renders C:\Users\me\.buzz/REPOS/ — mixed separators, functional but untidy.

Related

#3126 — the same [Workspace] section never reaches protocol-v1 harnesses (Claude Code, Codex) on any platform, because the legacy prompt-framing path never calls workspace_section at all. Independent of this predicate bug: a Windows Claude Code agent is affected by both, a macOS one only by #3126. This PR does not address it, and should not close it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FnfD8YHcZF5KbBTcLxc1P1

workspace_section() used cwd.starts_with('/') to detect absolute paths,
which is always false for Windows drive-letter paths (C:\Users\...).
Since cwd comes from std::env::current_dir() in the same process, this
meant Windows agents never received the [Workspace] grounding section.

Replace the string-prefix check with std::path::Path::is_absolute() +
parent().is_some(), which generalizes the original guard (reject
relative paths, reject the "/" current_dir() failure sentinel) to also
reject Windows roots (C:\, \\?\C:\) uniformly across platforms.

Gate the two POSIX-path assertions in the affected tests behind
#[cfg(unix)], since Path::is_absolute() correctly returns false for a
POSIX-style path on Windows, and extend the workspace_section doc
comment to record why the platform-dependent predicate is correct here
rather than a bug.

Fixes block#3124

Signed-off-by: Kyler Cao <kcao@gssmail.com>
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.

Windows agents never receive the [Workspace] system-prompt section: workspace_section() gates on a POSIX-only starts_with('/') predicate

1 participant