Skip to content

Fix Windows dev loop: beforeDevCommand script + Vite IPv4 bind + test_acp_client.py stdin-flush#8834

Open
seydousakho-star wants to merge 2 commits intoaaif-goose:mainfrom
seydousakho-star:windows-dev-fixes
Open

Fix Windows dev loop: beforeDevCommand script + Vite IPv4 bind + test_acp_client.py stdin-flush#8834
seydousakho-star wants to merge 2 commits intoaaif-goose:mainfrom
seydousakho-star:windows-dev-fixes

Conversation

@seydousakho-star
Copy link
Copy Markdown

Summary

Two small, surgical fixes found while bringing goose2 up on Windows 11.
Both are no-ops on macOS/Linux — they only affect the Windows code
paths.

  1. ui/goose2/justfilejust dev fails on Windows with a malformed
    Tauri --config argument. Three interacting causes in the
    beforeDevCommand.script string, fixed together because they share
    a code path:

    • cd ${PROJECT_DIR} && ... prefix — the unescaped && inside a
      JSON value gets split by Windows' bash → npm → tauri argv
      passthrough, truncating the --config JSON. Dropped; cwd already
      sets the working directory.
    • Leading exec — a bash builtin. Tauri runs beforeDevCommand via
      cmd.exe on Windows, which reports 'exec' is not recognized as an internal or external command. Harmless to drop on Unix.
    • Missing --host 127.0.0.1 — Vite 7 binds ::1 (IPv6 loopback)
      only on Windows by default, and WebView2 resolves localhost to
      IPv4 first, so the page never loads. Forcing IPv4 bind works on
      every platform.

    Also corrected cwd in the dev recipe from . to ... Tauri
    resolves beforeDevCommand.cwd relative to src-tauri/, not to the
    just-invocation dir. dev-debug already had ...

  2. test_acp_client.py — times out with Failed to initialize: None
    on Windows. Three layered causes:

    • stderr=subprocess.PIPE with nobody reading it. cargo run -p goose-cli -- acp writes several KB of compile progress to stderr;
      Windows' ~4 KB pipe buffer fills, the child blocks on stderr
      write, and the stdio loop deadlocks before initialize can
      resolve. Routed to DEVNULL — the test only cares about JSON-RPC
      framing on stdout.
    • bufsize=0 combined with text=True — text mode always uses
      io.TextIOWrapper which needs at least line buffering. bufsize=0
      made stdout flushes unreliable on Windows. Changed to bufsize=1.
    • (surfaced only after the above was fixed) cp1252 consoles can't
      encode the unicode progress glyphs (✓ ✗ 📝). Forced
      sys.stdout.reconfigure(encoding="utf-8") so the suite runs
      uniformly on Windows, Linux, macOS.

    Opportunistic: added an optional GOOSE_BIN env override plus
    automatic fallback to target/debug/goose[.exe] so the test can skip
    the cargo-run path when a pre-built binary exists. Cuts wall time
    from minutes (recompile + cargo noise) to under a second.

Test plan

  • Windows 11, Rust 1.92, Node 22, pnpm 10: just dev launches the
    native window, React UI renders, goose serve streams perf logs.
  • Windows 11: full 6-phase test_acp_client.py suite (initialize,
    session/new, session/prompt, re-initialize after restart,
    session/load, prompt-to-loaded-session) passes end-to-end
    against target/debug/goose.exe.
  • macOS: no behaviour change expected (dropping exec is harmless,
    --host 127.0.0.1 matches the default bind on Unix). Worth a
    reviewer confirmation.
  • Linux: same as macOS — no behaviour change expected.

No new deps, no config surface changes, no doc changes needed. The
only semantic shift on non-Windows platforms is test_acp_client.py
preferring target/debug/goose over cargo run when the binary
exists, which is a speed improvement.

Seydou Sakho added 2 commits April 24, 2026 14:16
`just dev` / `just dev-debug` on Windows fail in three ways that are all
localised to the `beforeDevCommand.script` tauri passes to the Vite
child process. Fixed together because they share a code path.

1. The `cd ${PROJECT_DIR} && ...` prefix in the `dev` recipe breaks the
   --config argv passthrough. The bare `&&` is visible to cmd.exe inside
   the JSON string and truncates everything after it, so Tauri gets a
   malformed config and fails before Vite starts. Dropped — cwd already
   handles the working dir.

2. The leading `exec` in both recipes is a bash builtin. Tauri runs
   beforeDevCommand through cmd.exe on Windows, which reports
   `'exec' is not recognized as an internal or external command`.
   Harmless to drop on Unix — pnpm/node handle their own lifecycles.

3. Vite 7 defaults to binding `::1` (IPv6 loopback) only on Windows.
   Tauri's WebView2 resolves `localhost` to IPv4 first and fails with
   "page cannot be loaded". Added `--host 127.0.0.1` to force Vite to
   bind IPv4. Works on Linux + macOS as well (those still bind 127.0.0.1
   by default, so the flag is a no-op there).

Also corrected `cwd` in the `dev` recipe from `.` to `..`: Tauri resolves
`beforeDevCommand.cwd` relative to `src-tauri/`, not to where `just`
was invoked. The `dev-debug` recipe already had `..`.

Tested on Windows 11 with Rust 1.92 + Node 22 + pnpm 10. `just dev`
now launches the native window, React UI renders, and `goose serve`
streams perf logs as expected. No change in behaviour on macOS/Linux.
`test_acp_client.py` times out with "Failed to initialize: None" on
Windows. Three layered causes, fixed together:

1. `stderr=subprocess.PIPE` with nobody reading it. When the command is
   `cargo run -p goose-cli -- acp`, cargo writes several KB of compile
   progress to stderr. Windows' pipe buffer (~4 KB) fills up, the child
   blocks on stderr write, and the stdio loop deadlocks before the
   initialize response is ever read. Routed to DEVNULL — this test
   cares only about JSON-RPC framing on stdout.

2. `bufsize=0` combined with `text=True` is unreliable on Windows. Text
   mode always goes through io.TextIOWrapper, which does its own
   buffering; the prior setting made `stdin.flush()` inconsistent.
   Changed to `bufsize=1` (line-buffered), which matches text-mode
   semantics on every platform.

3. (surfaced only after (1) was fixed) Windows consoles default to
   cp1252, which cannot encode the unicode progress glyphs (✓ ✗ 📝)
   the test prints. Forced `sys.stdout.reconfigure(encoding="utf-8")`
   at startup so the suite runs uniformly on Windows, Linux, macOS.

Also added an optional `GOOSE_BIN` env override + automatic fallback to
`target/debug/goose[.exe]` so the test can skip the cargo-run path when
a pre-built binary already exists (cuts wall time from minutes to
seconds, which matters when iterating on ACP behaviour).

Verified on Windows 11: full 6-phase suite (initialize, session/new,
session/prompt, re-initialize, session/load, prompt to loaded session)
now passes end-to-end.
Bojun-Vvibe added a commit to Bojun-Vvibe/oss-contributions that referenced this pull request Apr 26, 2026
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.

1 participant