cmd/ward does not compile on Windows: unguarded Unix-only syscalls (Setsid, Stat_t) #536

Closed
opened 2026-07-03 01:09:43 +00:00 by coilysiren · 0 comments
Owner

Summary

ward cannot be installed or built on Windows. There is no Windows path today:

  • No Windows release artifact. Releases ship ward-{darwin,linux}-{amd64,arm64} + SHA256SUMS only; the Homebrew tap is macOS/Linux. A Windows operator has nothing to download.
  • go install ./... fails to compile on windows/amd64. cmd/ward references Unix-only syscall symbols with no build guards:
# github.com/coilyco-flight-deck/ward/cmd/ward
cmd\ward\agent_drain_exit.go:83:41: unknown field Setsid in struct literal of type syscall.SysProcAttr
cmd\ward\container_bootstrap.go:406:33: undefined: syscall.Stat_t
cmd\ward\container_bootstrap.go:479:36: undefined: syscall.Stat_t

Both live in the Linux-only container / agent-driver subsystem (the drain-exit waiter's session detach; the docker-socket group grant and bot-credential group-ownership check), which the README already documents as depth-0 / unused on Windows. They just lack //go:build guards, so the whole main package fails and nothing downstream (ward exec, ward ops, git verbs, doctor, hooks) is reachable on Windows.

This matters because Windows is a declared ward host in the operating context (dev commands route through ward exec), but ward has evidently never been compiled there.

Proposed fix (small, mechanical)

Extract the two non-portable operations behind per-OS helpers; no command is stubbed out, the subsystem simply compiles everywhere:

  • detachProcess(*exec.Cmd) — Unix sets SysProcAttr{Setsid: true}; Windows no-op (the drain-exit waiter is Linux-container-only).
  • fileGID(os.FileInfo) (int, bool) — Unix reads Sys().(*syscall.Stat_t).Gid; Windows returns ok=false (no POSIX group ownership), and both callers already short-circuit on that.

After the split: go build ./... and go install ./... succeed on windows/amd64; go vet is clean; linux/darwin (amd64+arm64) still cross-compile; and every cmd/ward test covering the touched paths (drain, bootstrap-env, docker-create argv) passes on Windows.

Follow-up (separate issue, not this PR)

The cmd/ward test suite is now runnable on Windows for the first time and surfaces ~13 pre-existing Unix-assumption test failures unrelated to compilation: hardcoded /opt/homebrew/bin canonical paths in the hook path-check, filepath.Join separator assumptions in TestDestFromCloneArgs, fake gh/aws execs created without a .exe suffix, and the internal/agents/claude disk-report smoke test (Unix statfs via disk_other.go stub). These are test/feature portability, not build portability, and should be tracked and fixed separately.

## Summary `ward` cannot be installed or built on Windows. There is no Windows path today: - **No Windows release artifact.** Releases ship `ward-{darwin,linux}-{amd64,arm64}` + `SHA256SUMS` only; the Homebrew tap is macOS/Linux. A Windows operator has nothing to download. - **`go install ./...` fails to compile on `windows/amd64`.** `cmd/ward` references Unix-only `syscall` symbols with no build guards: ``` # github.com/coilyco-flight-deck/ward/cmd/ward cmd\ward\agent_drain_exit.go:83:41: unknown field Setsid in struct literal of type syscall.SysProcAttr cmd\ward\container_bootstrap.go:406:33: undefined: syscall.Stat_t cmd\ward\container_bootstrap.go:479:36: undefined: syscall.Stat_t ``` Both live in the Linux-only container / agent-driver subsystem (the drain-exit waiter's session detach; the docker-socket group grant and bot-credential group-ownership check), which the README already documents as depth-0 / unused on Windows. They just lack `//go:build` guards, so the whole `main` package fails and nothing downstream (`ward exec`, `ward ops`, git verbs, doctor, hooks) is reachable on Windows. This matters because Windows is a declared ward host in the operating context (dev commands route through `ward exec`), but ward has evidently never been compiled there. ## Proposed fix (small, mechanical) Extract the two non-portable operations behind per-OS helpers; no command is stubbed out, the subsystem simply compiles everywhere: - `detachProcess(*exec.Cmd)` — Unix sets `SysProcAttr{Setsid: true}`; Windows no-op (the drain-exit waiter is Linux-container-only). - `fileGID(os.FileInfo) (int, bool)` — Unix reads `Sys().(*syscall.Stat_t).Gid`; Windows returns `ok=false` (no POSIX group ownership), and both callers already short-circuit on that. After the split: `go build ./...` and `go install ./...` succeed on `windows/amd64`; `go vet` is clean; linux/darwin (amd64+arm64) still cross-compile; and every `cmd/ward` test covering the touched paths (drain, bootstrap-env, docker-create argv) passes on Windows. ## Follow-up (separate issue, not this PR) The `cmd/ward` test suite is now *runnable* on Windows for the first time and surfaces ~13 pre-existing Unix-assumption test failures unrelated to compilation: hardcoded `/opt/homebrew/bin` canonical paths in the hook path-check, `filepath.Join` separator assumptions in `TestDestFromCloneArgs`, fake `gh`/`aws` execs created without a `.exe` suffix, and the `internal/agents/claude` disk-report smoke test (Unix `statfs` via `disk_other.go` stub). These are test/feature portability, not build portability, and should be tracked and fixed separately.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#536
No description provided.