fix: guard Unix-only syscalls in cmd/ward so it builds on Windows #538

Merged
coilysiren merged 1 commit from fix/windows-cmd-ward-syscalls into main 2026-07-03 01:20:26 +00:00
Owner

cmd/ward referenced Unix-only syscall symbols with no build guards, so the
whole main package failed to compile on windows/amd64 and nothing downstream
(ward exec, ops, git verbs, doctor, hooks) was reachable there:

agent_drain_exit.go: syscall.SysProcAttr{Setsid: ...} (no Setsid field on Windows)
container_bootstrap.go: info.Sys().(*syscall.Stat_t) (undefined on Windows)

Both live in the Linux-only container / agent-driver subsystem, which the
README already documents as depth-0 / unused on Windows; they just lacked
//go:build guards. Extract the two non-portable operations behind per-OS
helpers so the subsystem compiles everywhere without stubbing any command:

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/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 passes on Windows. The remaining Windows test
failures are pre-existing Unix assumptions in unrelated tests, now runnable for
the first time, and are called out for separate follow-up.

closes #536

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Summary

Checklist

  • I opened an issue first and referenced it above (see CONTRIBUTING.md).
  • The change stays within ward's scope (the dev-verb gate / agent driver), not a personal-infra or downstream-repo verb.
  • I ran the dev verbs locally: ward exec build, ward exec test, ward exec vet, ward exec lint.
  • Docs updated where behaviour changed (docs/, README.md, docs/FEATURES.md).
cmd/ward referenced Unix-only syscall symbols with no build guards, so the whole main package failed to compile on windows/amd64 and nothing downstream (ward exec, ops, git verbs, doctor, hooks) was reachable there: agent_drain_exit.go: syscall.SysProcAttr{Setsid: ...} (no Setsid field on Windows) container_bootstrap.go: info.Sys().(*syscall.Stat_t) (undefined on Windows) Both live in the Linux-only container / agent-driver subsystem, which the README already documents as depth-0 / unused on Windows; they just lacked //go:build guards. Extract the two non-portable operations behind per-OS helpers so the subsystem compiles everywhere without stubbing any command: 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/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 passes on Windows. The remaining Windows test failures are pre-existing Unix assumptions in unrelated tests, now runnable for the first time, and are called out for separate follow-up. closes https://forgejo.coilysiren.me/coilyco-flight-deck/ward/issues/536 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> <!-- ward is Forgejo-canonical and mirrored read-only to GitHub. GitHub is the external front door for everyone except the maintainer: fork, push a branch, open your PR here. A maintainer replays an accepted PR onto Forgejo `main` and closes the matching Forgejo issue. If you are working directly in the canonical repo, use Forgejo instead. See CONTRIBUTING.md. --> ## Summary <!-- What does this change do, and why? --> ## Related issue <!-- Link the GitHub issue this addresses, e.g. Fixes #123. The internal Forgejo `closes #N` link is added by whoever carries the change across - you don't need it unless you're the maintainer working directly on Forgejo. --> ## Checklist - [ ] I opened an issue first and referenced it above (see CONTRIBUTING.md). - [ ] The change stays within ward's scope (the dev-verb gate / agent driver), not a personal-infra or downstream-repo verb. - [ ] I ran the dev verbs locally: `ward exec build`, `ward exec test`, `ward exec vet`, `ward exec lint`. - [ ] Docs updated where behaviour changed (`docs/`, `README.md`, `docs/FEATURES.md`).
cmd/ward referenced Unix-only syscall symbols with no build guards, so the
whole main package failed to compile on windows/amd64 and nothing downstream
(ward exec, ops, git verbs, doctor, hooks) was reachable there:

  agent_drain_exit.go:  syscall.SysProcAttr{Setsid: ...}  (no Setsid field on Windows)
  container_bootstrap.go: info.Sys().(*syscall.Stat_t)     (undefined on Windows)

Both live in the Linux-only container / agent-driver subsystem, which the
README already documents as depth-0 / unused on Windows; they just lacked
//go:build guards. Extract the two non-portable operations behind per-OS
helpers so the subsystem compiles everywhere without stubbing any command:

  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/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 passes on Windows. The remaining Windows test
failures are pre-existing Unix assumptions in unrelated tests, now runnable for
the first time, and are called out for separate follow-up.

closes #536

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.