ci: run the full suite on macOS, and matrix all three platforms together - #781
ci: run the full suite on macOS, and matrix all three platforms together#781noahsabaj wants to merge 4 commits into
Conversation
|
The matrix is the right place to catch the Windows daemon gaps being reported in #841 and #917. Please include a smoke case where a default named-pipe daemon has no worker descriptor and is still found by |
|
Thanks — taking the three in turn. Herdr. The premise does not hold in this tree. The daemon cases. Both are worth having, and I do not think they belong in this PR. This one changes CI wiring only: it adds macOS, folds the three platforms into one The right home is the port PRs that own those paths — #841 is session-lease recovery and #917 is orphan-tree teardown. Once the matrix lands, any suite added there runs on all three platforms by construction, which is the point of doing it this way round. |
macOS is a supported platform with no CI at all, and the Linux and Windows coverage was two hand-maintained jobs that had already drifted: Windows never ran the `ai`, process-smoke, or kernel suites, and nothing reported that gap. Replace both with one matrix over (os x suite). A suite added to the list now runs on every platform by construction rather than by remembering to copy it. Per-suite settings come from `include`, and only the steps that genuinely differ -- system packages and uv -- branch on `runner.os`. macOS takes uv from Homebrew: `pip install --user` puts its scripts under ~/Library/Python/<version>/bin, not ~/.local/bin. Windows asks sysconfig for the user scripts directory, which carries the interpreter version (%APPDATA%\Python\Python313\Scripts) -- the fixed %APPDATA%\Python\Scripts it used before never held uv, so every Windows job needing the Python kernel failed at bootstrap. Windows legs run `continue-on-error` for now. They report their real state without gating the merge, because the native Windows port is still landing in other PRs; the line comes out once it has. The nightly process-stress workflow gets the same three-platform matrix, since it exercises the process-teardown paths that differ most across platforms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adding macOS to CI turns up the failure reported in PrimeIntellect-ai#669 straight away. `sockaddr_un.sun_path` is 104 bytes on macOS and the BSDs, and a stock macOS $TMPDIR already spends 49 of them, so the default worker socket path measures 102. A five-digit uid, or a $TMPDIR redirected somewhere deeper by a sandbox or a test, overruns the field. The overrun does not announce itself as "name too long": the name is truncated, the server binds one path, clients dial another, and it surfaces 30 seconds later as a daemon create timeout. Fall back to a short directory under /tmp, but only when the longest socket name would not otherwise fit, so Linux and the default macOS layout keep the exact paths they have today. The fallback name includes a hash of the preferred directory, so processes sharing a $TMPDIR agree on it while separate $TMPDIRs stay separate -- an isolated temporary directory keeps isolating. Overlaps with PrimeIntellect-ai#722 and PrimeIntellect-ai#687, which fix the same report; this variant is here so the macOS CI legs added alongside it go green. Happy to drop it in favour of either if one lands first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The fallback hashes the preferred directory name, but this branch is cut from main, where daemon-socket.ts had no reason to import node:crypto. The Windows port branch does import it for its pipe prefix, which is why the reference type-checked there and only failed here — I verified the wrong branch. Caught by `npm run build` on macOS and Linux: daemon-socket.ts(249,14): error TS2304: Cannot find name 'createHash'. Now verified on this branch specifically: npm run build, npm run check, and daemon-socket 8/8. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two assumptions in the new telemetry suite hold on Unix and cannot hold on Windows, so both cases failed there the moment the file landed. Windows does not implement POSIX permission bits. A file written with mode `0o600` reads back as `0o666`, so `statSync().mode & 0o777` cannot observe the private mode the product asks for. Guard that one assertion rather than skipping the case, because the identity and persistence assertions around it are worth running everywhere. Creating a file symlink needs SeCreateSymbolicLinkPrivilege, which only Developer Mode or an elevated shell grants, so `symlinkSync` throws EPERM on an ordinary account. Probe the privilege once and skip the symlink case when it is absent, matching how `packages/tui/test/autocomplete.test.ts` handles the same limitation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
69f2057 to
577285b
Compare
|
Rebased onto current
Both fail deterministically on Windows 11 today and pass with the commit. This is the same reason the macOS Still no CI run on this PR — the checks sit at |
Why
macOS is a supported platform with no CI at all, and Linux and Windows coverage were two
hand-maintained jobs that had already drifted apart: Windows never ran the
ai, process-smoke,or kernel suites, and nothing reported the gap.
Adding macOS surfaced a real bug immediately — the one reported in #669 — which is included
here so the new legs go green rather than red.
What changes
One matrix over
(os × suite). A suite added to the list now runs on every platform byconstruction rather than by remembering to copy it into a second job. Per-suite settings come
from
include; only the steps that genuinely differ — system packages and uv — branch onrunner.os.pip install --userputs its scripts under~/Library/Python/<version>/bin, not~/.local/bin, so the Linux step could not be reused.sysconfigfor the user scripts directory, which carries the interpreterversion (
%APPDATA%\Python\Python313\Scripts). The fixed%APPDATA%\Python\Scriptsit usedbefore never held uv, so every Windows job needing the Python kernel failed at bootstrap.
continue-on-error. They report their real state without gating themerge, because the native Windows port is still landing in other PRs (fix(coding-agent): resolve kernel venv interpreter for Windows layout #663, fix(coding-agent): hide console windows for background child processes #664, fix(coding-agent): tolerate unsupported directory fsync #670, fix(coding-agent): bootstrap IPython kernel venv with the Windows interpreter path #695,
feat(coding-agent): add Windows PowerShell installer #716, fix: keep worker socket paths under the sun_path limit #722, fix(coding-agent): reclaim stale session leases on Windows #727, Add native Windows installation and launchers #732, feat(coding-agent): add native Windows support #744, fix(coding-agent): cache process start id to fix daemon handshake livelock on Windows #748). Delete that one line once it has, and Windows gates like
the other two.
The nightly process-stress workflow gets the same three-platform matrix, since it exercises the
process-teardown paths that differ most across platforms.
The macOS fix (
fix(macos): keep daemon socket paths inside sun_path)sockaddr_un.sun_pathis 104 bytes on macOS and the BSDs, and a stock macOS$TMPDIRalreadyspends 49 of them. Measured against the longest name the daemon creates:
The overrun does not announce itself as "name too long": the name is truncated, so the server
binds one path while clients dial another, and it surfaces 30 seconds later as a daemon
createtimeout.The fallback engages only when the longest socket name would not otherwise fit, so Linux
and the default macOS layout keep byte-identical paths — on Linux it is unreachable at any
possible uid. The fallback directory name includes a hash of the preferred one, so processes
sharing a
$TMPDIRagree on it while separate$TMPDIRs stay separate, which keeps anisolated temporary directory isolating.
Overlaps with #722 and #687, which fix the same report. This variant is here so the macOS
legs added alongside it go green; happy to drop it in favour of either if one lands first. The
difference worth keeping is the hash — a flat
/tmp/prime-agent-<uid>collapses two isolatedTMPDIRs into one directory.Verification
Build and checkand the Linux suites pass unchanged.sun_pathfix; without it,coding-agent 1/3fails on worker socketbinding.
Note for reviewers
Individual job names change (
Build and check→Build and check (ubuntu-latest), etc.), so anybranch-protection rules pinned to the old names need updating. The aggregate
build-check-testjob keeps its name and remains the single required check.
🤖 Generated with Claude Code
Note
Run CI and nightly stress tests across Ubuntu, macOS, and Windows in a matrix
ubuntu-latest,macos-latest, andwindows-latest; job timeouts are increased from 15 to 30 minutes.apt, Homebrew, Chocolatey) anduv;uvis installed via Homebrew on macOS andpip --useron Linux/Windows with the appropriate bin directory added toPATH.defaultDaemonSocketDirin daemon-socket.ts to fall back to a deterministic SHA-256-hashed/tmpsubdirectory when thetmpdir-based socket path would exceed the platform's UNIX domain socket path limit (104 bytes on macOS, 108 on Linux).continue-on-error: true).Macroscope summarized 577285b.