Repository navigation
Description
What happened
Running the full offline suite (./scripts/test-acq-bats, no file argument — 545 tests) on a real macOS host surfaces 7 failures, all sharing the identical root cause:
not ok 119 clone(msb): --clone mounts a scratch clone at the original path and registers the sandbox remote
not ok 128 clone(msb): secondary workspaces keep their direct mounts
not ok 157 msys: a mount uses the host form for SOURCE and the guest form for TARGET
not ok 158 msys: recorded github-scope workspace uses the host form
not ok 223 github-scope: uses recorded sandbox workspace when path is omitted
not ok 370 msb: provision binds USAi + GitHub via --secret with --tls-intercept, no value leak
not ok 391 msb: multi-workspace mounts each at its host path; start dir is the primary
All 538 other tests pass. This is a test-construction fragility, not a defect in acq itself — flagging per the "Track Deferred Work" rule in AGENTS.md rather than leaving it silently observed.
Root cause
On macOS, /var and /tmp are symlinks to /private/var and /private/tmp (readlink /var → private/var). scripts/test-acq-lib.sh's acq_setup_stubs builds $STUBDIR directly from the raw environment:
STUBDIR=$(mktemp -d "${TMPDIR:-/tmp}/acq-test.XXXXXX")$TMPDIR on macOS is /var/folders/.../T/ — the unresolved symlink form, with a trailing slash. Several @test blocks then build their OWN expected-value regex by hand, directly against $STUBDIR or $BATS_TEST_TMPDIR (which inherits the same unresolved form), e.g. (test/bats/116-clone-option.bats):
assert_regex "$line" "--volume $(host_path "$scratch"):${repo}( |\$)"But the ACTUAL value acq emits goes through its own path-canonicalization logic (host_path/canonicalize_path in acq.backends/common.sh, ADR-0029) somewhere along the way, which resolves the symlink to its physical target. So the real argv has /private/var/folders/.../T/acq-test.XXXXXX/... (resolved, single slash), while the test's hand-built expectation has /var/folders/.../T//acq-test.XXXXXX/... (unresolved, doubled slash from the trailing / + the literal / the test code appends).
Confirmed directly:
PATTERN: --volume /var/folders/ts/.../T//acq-test.X1zUbF/state/clones/.../cloneproj:...
VALUE : --volume /private/var/folders/ts/.../T/acq-test.X1zUbF/state/clones/.../cloneproj:...
Two distinct symptoms, same cause (the test's expected string is built from the raw, unresolved $TMPDIR rather than through the same canonicalization acq applies to the real value):
- Missing
/privateprefix in the expectation. - A doubled
//in the expectation, from$TMPDIR's own trailing slash plus the test's own/-prefixed concatenation.
Why this doesn't show up in CI
Linux's /tmp is not a symlink and typically has no trailing slash in $TMPDIR (often unset, defaulting to /tmp), so this specific macOS-only path-resolution mismatch never triggers there. This is presumably why it's gone unnoticed — the suite is green in CI but red on a real macOS development machine.
Suggested fix
Resolve $STUBDIR's real/physical path once, at acq_setup_stubs time, e.g.:
STUBDIR=$(mktemp -d "${TMPDIR:-/tmp}/acq-test.XXXXXX")
STUBDIR=$(cd "$STUBDIR" && pwd -P)so every test's hand-built expectation and acq's own canonicalized output start from the same resolved base path, with no further per-test workaround needed. Have not implemented this — filing for someone with more context on the test harness's design intent (and to confirm this fix doesn't have knock-on effects on the Windows/MSYS path-forms tests, which deliberately exercise host-vs-guest path translation and may have their own reasons to care about the raw vs. resolved distinction).
Reproduction
./scripts/test-acq-bats # macOS, real $TMPDIR with a /var symlink7/545 fail with the signature above; 538/545 pass.
Activity