Skip to content

ci: run the daemon and CLI unit suites on Windows - #1536

Open
spacedragon wants to merge 10 commits into
mainfrom
dev/yulong/tubeworm
Open

ci: run the daemon and CLI unit suites on Windows#1536
spacedragon wants to merge 10 commits into
mainfrom
dev/yulong/tubeworm

Conversation

@spacedragon

Copy link
Copy Markdown
Contributor

What

The daemon (runtimes, skills, spawn driver, IPC paths) and the CLI (junction-based version pointers) are supported on Windows after #1532 / #1533, but nothing ever ran there — the win32 branches were only exercised by simulating the platform on Linux.

This adds a Unit Test (Windows) job on windows-latest that runs both packages' unit suites, plus the seam a Windows-green suite needs:

  • WINDOWS_EXCLUDED in packages/{daemon,cli}/vitest.config.ts — whole files whose every case is POSIX-only (a filesystem path handed to net.Server.listen, mode & 0o777 assertions, POSIX login-shell semantics). Applied only when the platform is Windows, so vitest run is green for a Windows contributor too and the Linux jobs are unchanged.
  • A single non-portable case keeps using the suite's existing it.skipIf(process.platform === 'win32') idiom — packages/cli/test/install.test.ts gains one.
  • test/windows-exclusions.test.ts in both packages fails if a list entry stops naming a real file, so an exclusion cannot go stale and silently let a file back into the Windows job (or keep a since-fixed file out of it forever).
  • core.autocrlf false before checkout, so fixtures and golden files are byte-identical to the Linux jobs.

Note on the exclusion list

The initial list is seeded from static analysis, not from a Windows run — this PR's own CI is the first time the suite executes on windows-latest. Expect one or two rounds of convergence on that job's output before it is green; each addition lands with the one-line reason it is POSIX-only.

🤖 Generated with Claude Code

The daemon (runtimes, skills, spawn driver, IPC paths) and the CLI (junction
version pointers) are supported on Windows, but nothing ran there — the win32
branches were only ever exercised by simulating the platform on Linux.

Adds a `Unit Test (Windows)` job on `windows-latest` for those two packages, and
the seam a Windows-green suite needs: a per-package `WINDOWS_EXCLUDED` list,
applied only when the platform IS Windows, for files whose every case is
POSIX-only. A single non-portable case keeps using the suite's existing
`it.skipIf(process.platform === 'win32')` idiom; `windows-exclusions.test.ts`
fails if a list entry goes stale.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-scoped PR. Verified the diff at the trusted head (22150b5, merge parents match base/head exactly):

  • unit-windows CI job on windows-latest, correctly running pnpm --filter daemon --filter cli test:unit, core.autocrlf false set before checkout, summary merged/published following the existing job's pattern.
  • WINDOWS_EXCLUDED lists in both vitest.config.ts files — checked every listed file exists and spot-checked the stated reasons: net.Server.listen(path) in mcp-bridge-e2e.test.ts/shim-tunnel.test.ts, mode & 0o777 assertions in config-file-env.test.ts/runtime-launch.test.ts/skills-cli-cell.test.ts — all accurate.
  • New windows-exclusions.test.ts in both packages guards against stale entries (unconditionally runs, checks file existence + no dupes) — good.
  • install.test.ts gets a scoped it.skipIf(win32) for the one non-portable case, as described.

Minor, non-blocking observation: unit-windows has no defer_summaries output-export branch (unlike the unit job's export-summary step), so if this workflow is ever called from release.yaml with defer_summaries: true, the Windows summary is silently dropped rather than surfaced by the caller. Not a correctness issue for the PR's stated goal (get the Windows job running on PRs) — just worth a follow-up if the release gate later wants Windows results too.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: the new Unit Test (Windows) gate is red on this exact revision, so the PR does not yet deliver a runnable Windows unit suite. The job reports 17 CLI failures across 8 files, including service-systemd/launchd path expectations, service root resolution, login command quoting, POSIX shell semantics, and version-lock process identity. Because pnpm stops after the first filtered package failure, the daemon suite did not reach a final result either, so the job has not yet validated both claimed packages. Please make the affected cases platform-neutral or apply the documented per-case/all-file exclusion policy, then rerun until the job is green and both daemon and CLI summaries complete. All non-Windows CI jobs passed, and git diff --check passed; local pnpm verification was unavailable because this review runner could not access a writable/downloadable Corepack cache.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

Comment thread .github/workflows/test.yaml Outdated
VITEST_JOB_SUMMARY_DIR: ${{ runner.temp }}
run: >
GITHUB_STEP_SUMMARY="$CAPTURED_JOB_SUMMARY"
pnpm --filter @agentconnect.md/daemon --filter @agentconnect.md/cli test:unit

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new job currently exits 1: the CLI suite has 17 failures across 8 files, and pnpm then stops before the daemon suite reaches a final result. That means this gate has not yet exercised both packages successfully. Please converge the platform-neutral assertions/skips/exclusions and rerun this command until both suites complete green.

First `Unit Test (Windows)` run: 17 CLI failures, and a recursive `pnpm run`
aborting its siblings on the first one hid the daemon suite entirely. Splits the
job into one step per package so both always report, and fixes what the CLI
failures actually were:

- `homedir()` reads USERPROFILE on Windows, so stubbing HOME alone left the real
  home in play — seven cases across service-instance/service-index.
- One expectation hardcoded a POSIX-joined path the mock records separator-correct.
- launchd/systemd/`shellExecArgv` only ever target a POSIX host, so their files
  join WINDOWS_EXCLUDED rather than assert Windows-shaped output.
- Two cases document real Windows gaps and skip with the reason: `shellArg`
  quotes with POSIX single quotes, and `procStartTime` shells out to `ps`, so the
  version lock cannot detect PID reuse there.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes verified against the previous REQUEST_CHANGES findings (17 CLI failures, daemon suite not reached):

  • Split the single --filter daemon --filter cli step into two steps, CLI gated on !cancelled() — pnpm's fail-fast recursive run no longer hides the daemon suite behind a CLI failure.
  • New WINDOWS_EXCLUDED entries (shell-exec.test.ts, service-launchd.test.ts, service-systemd.test.ts) — checked each: shellExecArgv asserts POSIX-only argv, launchd/systemd tests build platform-specific unit files. Reasons match the code.
  • it.skipIf(win32) added to login.test.ts (POSIX shell-quoting assertion) and version-lock.test.ts (PID-reuse detection shells out to ps, absent on Windows) — both accurate.
  • ensure-daemon.test.ts now uses join() instead of a hardcoded /-separated path; service-index.test.ts/service-instance.test.ts stub USERPROFILE alongside HOME since that's what Node's homedir() reads on Windows — correct.

No remaining concerns from code inspection; didn't have Windows CI available to re-run in this environment.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

The first full Windows run of the daemon suite: 179 failures over 54 files. Most
were the tests' own POSIX assumptions, but three were the daemon's:

- `dream-skills.ts` and `skill-sandbox-policy.ts` fsync a directory with no
  win32 guard, unlike `write-agent.ts` / `config-revision.ts`, so EPERM took out
  dream-skill publication and — through `persistSkillSandboxRequirement` — every
  `runChat` launch. Guarded both, the way the other two already were.
- `home(env)` in the runtime probe read USERPROFILE on Windows and nothing else,
  so a caller pinning only HOME silently resolved to the daemon's own home. It
  now falls back to HOME there, the way Git for Windows reads it, and the whole
  runtime-probe layer became testable on Windows at all.
- The skills CLI's Windows process fallback — the one case #1532 added for
  Windows and nothing ever ran there — fails with SkillLedgerSafetyError. Left
  disabled with the reason, not skipped by platform.

The rest: the sandbox-pod plane is Linux by construction, so its files join
WINDOWS_EXCLUDED; the pool suites stand up a second daemon on one root, which
EADDRINUSEs because `start()` clears a stale UDS and a named pipe has no
equivalent, so they wait on that fix; X_OK, mode-bit, signal and O_NOFOLLOW cases
skip per case with the reason. Windows gets double the test timeout — its I/O is
slower by enough to time out on the host rather than the code.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The daemon-side CI convergence work itself checks out: WINDOWS_EXCLUDED additions (sandbox-pod plane, EADDRINUSE on shared-root pool tests) match the actual test bodies, the USERPROFILE/HOME fallback fix in probe.ts is correct, and the timeout-minutes/testTimeout bumps are reasonable given Windows I/O cost.

One real concern, not introduced by this PR but surfaced and left unresolved by it: several tests are now skipped on Windows because O_NOFOLLOW — the daemon's stated security boundary against a symlink planted in an agent-writable directory (see the SECURITY docstring in packages/daemon/src/memory/fs.ts) — has no Windows equivalent and is silently a no-op there. This isn't cosmetic like the mode-bit/signal skips elsewhere in the diff: it means the symlink-escape protection in memory/fs.ts, shim/fd-memory-fs.ts, shim/safe-descent.ts, and several skills/* install/snapshot paths is inert on a platform this repo documents as a supported self-hosted deployment target (packages/daemon/test/memory-fs.test.ts:55, test/memory.test.ts:148, test/workspace-reader.test.ts:276).

Each spot says "tracked separately," but I searched open/closed issues in this repo and found nothing referencing this gap — so right now it's an inline claim, not a tracked one. Before merging, please either open the actual issue those comments point to, or add a cross-platform compensating check (e.g., lstat the resolved leaf and reject a symlink before opening, which doesn't depend on O_NOFOLLOW) so Windows daemons aren't running with a documented security control quietly disabled.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: the production Windows portability adjustments look reasonable and all completed non-Windows checks pass, but the new daemon exclusion list now removes broad portable coverage in violation of its own documented policy. orchestration.test.ts is excluded under the claim that every case starts two daemons on one root; in fact, roughly the first 18 cases each boot one daemon on a fresh root and contain no POSIX-only path, signal, or permission assumptions. Only the later pool-duty section uses two simultaneous daemons. Please keep the single-daemon orchestration cases in the Windows run and scope the Windows skip/exclusion to the genuinely multi-daemon portion. The Windows job was still running when this review completed; git diff --check passed.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

Comment thread packages/daemon/vitest.config.ts Outdated
// Every case stands up a second daemon on one root, which EADDRINUSEs on Windows: `start()` clears
// a stale UDS before listening and a named pipe has no equivalent. Restore once that is fixed.
'test/schedule-catchup.test.ts',
'test/orchestration.test.ts',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file does not satisfy the all-cases rule above. Most of orchestration.test.ts (the record-first, correlation, completion, owner, and single-daemon deadline cases) calls boot(root) only once and has no POSIX-only assumptions; only the pool-duty section opens two daemons concurrently. Excluding the whole file silently drops broad Windows orchestration coverage. Please scope the skip to the multi-daemon section (or split that section into its own excluded file) and leave the portable cases running.

179 → 5 after the previous round. One of the five was the daemon's again:
`publishAcceptedDreamSkill` reads only ENOTEMPTY (Linux) and EEXIST (Darwin) as
"this digest was already published", and Windows reports EPERM for the same
rename onto an existing directory — so republishing identical reviewed bytes
threw instead of being idempotent. EPERM is broad there, so it counts as a
collision only on win32, and the digest re-read still decides.

The other four are the tests': an npx launcher resolves to `npx.cmd`; a trusted
executable fixture is an extensionless 0755 symlink; a listing pads its names
with `"`. The fourth is a finding, not a fixture — a background memory write
races teardown and its atomic rename hits EPERM, because Windows cannot replace
a file another handle holds open. Skipped with that reason.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This revision's five fixes are correct — verified each against the actual code:

  • dream-skills.ts: treating EPERM as a possible collision on Windows rename() is fail-safe, since it's gated by a digest re-read (inspectLocalSkillSource) that throws if the existing bytes don't actually match.
  • model-catalog.test.ts: npx resolving to a .cmd/.exe launcher on Windows PATH lookup — correct.
  • read-roots.test.ts: extensionless-symlink-at-0755 doesn't match Windows PATH resolution — correct skip.
  • workspace-reader.test.ts: " is illegal in a Windows filename — correct skip.
  • daemon-lifecycle.test.ts: plausible Windows file-locking difference (can't replace a file another handle holds open), consistent with the others.

Two concerns carried over from the previous revision are still unaddressed here (this diff doesn't touch either):

  1. test/orchestration.test.ts is still fully excluded from the Windows job via WINDOWS_EXCLUDED, even though only ~5 of its ~20 cases (the duty-handoff ones, from daemon2 at line 402 onward) spin up a second daemon on one root. The other ~15 — subtask reporting, deadline arming, cancel/idempotency, ownership checks — use a single shared daemon and have no POSIX-only assumption. Whole-filing this drops real Windows coverage that a per-case it.skipIf would keep.
  2. The O_NOFOLLOW-is-inert-on-Windows gap (symlink-escape protection in memory/fs.ts, shim/fd-memory-fs.ts, shim/safe-descent.ts, several skills/* paths) is still only "tracked separately" in comments with no actual linked issue — I re-checked and still find none in the repo's issues.

Neither blocks the mechanics of this specific commit, but both are open findings against the revision as a whole and should be resolved (or given a real tracking issue) before merge.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: the blocking Windows-coverage issue remains on 539fc770. The exact head still puts test/orchestration.test.ts in WINDOWS_EXCLUDED under the claim that every case starts a second daemon on one root, but the record-first, correlation, completion, owner-check, end-to-end, and startup-rearm sections (roughly lines 128–412) each use a single boot(root) and contain no POSIX-only assumptions; only the later pool-duty section opens two daemons concurrently. Excluding the whole file therefore drops broad portable orchestration coverage and contradicts the list's documented all-cases rule. Please scope the Windows skip to the multi-daemon section or split that section into its own excluded file. This revision's Dream-skill EPERM collision handling and individual fixture skips look reasonable by inspection; CI was still running when this review completed.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

Round 4 came back with six failures, five of them timeouts in files that pass an
inline 15 s budget per test — and a different five than round 3's, which is what
contention looks like rather than a hang. The Windows runner has 4 vCPUs and this
suite spawns real child processes, so it now runs two workers there instead of
four; the raised global timeout cannot help a test that names its own.

The sixth: `npx` resolves to `npx.CMD` on this runner, uppercase.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This revision's changes are correct and low-risk: halving maxWorkers to 2 on the 4-vCPU Windows runner is a reasonable fix for tests tipping over their inline timeout budget under contention, and the case-insensitive .CMD match in model-catalog.test.ts matches real Windows PATHEXT resolution.

Neither of the two outstanding blockers from the prior revision is touched by this diff, so they still stand:

  1. test/orchestration.test.ts remains wholly excluded from the Windows job (packages/daemon/vitest.config.ts:52) even though only its duty-handoff cases (from the second-daemon setup onward) need it — the ~15 single-daemon cases (subtask reporting, deadline arming, cancel/idempotency, ownership) have no POSIX-only dependency and are still losing Windows coverage that a per-case it.skipIf would preserve.
  2. The O_NOFOLLOW-inert-on-Windows symlink-escape gap (memory/fs.ts, shim/fd-memory-fs.ts, shim/safe-descent.ts, several skills/* paths) is still only "tracked separately" in comments (test/memory.test.ts:148, test/memory-fs.test.ts:55, test/workspace-reader.test.ts:276) with no linked issue in the repo.

Please resolve or link real tracking for both before this is mergeable.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: the blocking Windows-coverage issue remains on b26f47c2. This revision correctly makes the npx.cmd assertion case-insensitive and reduces Windows daemon workers to avoid load-dependent inline timeout failures, but it leaves test/orchestration.test.ts in WINDOWS_EXCLUDED. That file still contains roughly 18 portable single-daemon cases covering record-first persistence, correlation safety, completion, owner checks, end-to-end replies, and startup re-arm; only its pool-duty section opens two daemons concurrently. Whole-file exclusion therefore contradicts the documented all-cases rule and silently removes broad Windows orchestration coverage. Please scope the Windows skip to the multi-daemon section or split that section into its own excluded file. git diff --check passed; CI was still running when this review completed.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

The round-4 timeouts are gone at two workers — 27 min instead of 15, still well
inside the cap — and what surfaced underneath was an unhandled rejection that
moves between test files run to run: `atomicWriteContainedMemoryFile` renames its
temp over MEMORY.md, and Windows refuses to replace a file another handle holds
open. A file just written transiently is one, to the runner's own scanner. So it
failed whichever test happened to be running, which is why it read as a different
flake each round; retrying the publish bounded is what npm and cacache do for the
same reason.

`skill install ledger on Windows` joins skills-cli-golden's Windows case as
disabled: both fail on `write EPIPE` from skill-workspace-mutator.ts, the gated
helper exiting before its stdin write lands. Two independent Windows-only cases on
one gap.

Comments added across this branch tightened to CLAUDE.md's one-line rule.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good progress: publishOverTarget's bounded retry on EPERM/EACCES/EBUSY in memory/fs.ts is a real fix for the "Windows can't rename over a file another handle holds open" race, not just another skip — that's the right kind of change. One follow-up worth checking: daemon-lifecycle.test.ts:1091 is still it.skipIf(win32) with a comment describing exactly this symptom ("its atomic rename hits EPERM") — now that the underlying race has a retry, is that skip still necessary, or was removing it just missed in this commit?

New concern in this revision: skill-install-ledger.test.ts and skills-cli-golden.test.ts both convert their Windows-only test case from a live it(...) (present since before this whole PR) to an unconditional it.skip, because it now fails with SkillLedgerSafetyError / write EPIPE from skill-workspace-mutator.ts. Unlike the platform-portability skips elsewhere in this PR, this isn't "no POSIX equivalent" — it's a real functional bug in skill installation through the gated helper on Windows, i.e. exactly the "skills" capability this PR's own description claims is supported (#1532/#1533). Disabling both tests with no linked tracking issue removes the only coverage of a currently-broken code path. I could not find an issue for this (searched SkillLedgerSafetyError, skill-workspace-mutator, EPIPE).

Carried over from prior revisions, still unaddressed:

  1. test/orchestration.test.ts remains wholly excluded from the Windows job despite only its duty-handoff cases needing it.
  2. The O_NOFOLLOW-inert-on-Windows symlink-escape gap across memory/fs.ts/shim/*/skills/* is still only "tracked separately" in comments with no linked issue.

Please open real tracking issues for the skill-install and O_NOFOLLOW gaps (or fix them), and narrow the orchestration exclusion, before this is mergeable.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Windows-only bounded retry around the atomic memory-file publish looks reasonable, and the accompanying comment-only/test-disable changes do not introduce another blocker. However, the Windows coverage blocker remains at this exact revision: WINDOWS_EXCLUDED still removes all of test/orchestration.test.ts, while the file's cases through the startup re-arm section boot only one daemon and do not depend on the shared-root named-pipe limitation. Only the pool-duty section uses bootPool() to start two daemons on one root. Please keep the portable orchestration cases in the Windows suite by scoping the skips to the affected pool cases or splitting that section into its own file.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

Comment thread packages/daemon/vitest.config.ts Outdated
// Every case stands up a second daemon on one root, which EADDRINUSEs on Windows: `start()` clears
// a stale UDS before listening and a named pipe has no equivalent. Restore once that is fixed.
'test/schedule-catchup.test.ts',
'test/orchestration.test.ts',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This remains broader than the stated rule for WINDOWS_EXCLUDED. In the exact head, orchestration.test.ts has many single-daemon cases from lines 128–408; only the pool-duty section starting at line 413 calls bootPool() and opens the same root twice. Excluding the whole file drops substantial portable orchestration coverage from the new Windows job. Please skip/split only the pool-duty cases.

…default

Round 6: the memory-publish retry held (durable-inbox green, no unhandled
rejection), and the two failures left were inline-15 s timeouts again — in yet
another pair of cases. Two workers reduced the contention without clearing it,
because the config default cannot help a test that names its own budget.

Those 352 `}, 15_000)` arguments date from a 5 s default. Against today's 30 s
(60 s on Windows) they only shorten the budget, and a timeout can only fail a
test, never pass one — so removing them raises headroom on both platforms and
takes the per-platform tuning back to the one place that has it. Budgets above the
default (20 s and up) are deliberate and stay.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This revision is a clean, purely mechanical cleanup — verified every changed line across all 31 files diffs down to exactly }, 15_000)}), no test logic touched. Good catch too: those inline 15s budgets predated (and were shorter than) the new 30s/60s config default, so they were silently re-shortening the very Windows budget the earlier commits raised.

Three blockers carried from prior revisions are still open (none touched here):

  1. test/orchestration.test.ts remains wholly excluded from the Windows job (vitest.config.ts:52) though only its duty-handoff cases need the shared-root carve-out.
  2. The O_NOFOLLOW-inert-on-Windows symlink-escape gap (memory/fs.ts, shim/*, skills/*) is still only "tracked separately" in comments, no linked issue found.
  3. skill-install-ledger.test.ts/skills-cli-golden.test.ts still unconditionally it.skip a previously-live Windows test that now fails with SkillLedgerSafetyError/EPIPE in the skill-install gated helper — a real functional gap in Windows skill installation, no linked issue found.

Please resolve or link real tracking for these before merge.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout cleanup itself is sound: I verified that all 352 test-file edits mechanically remove only obsolete 15_000 overrides, so those cases now inherit the existing 30-second Linux / 60-second Windows configuration. This revision does not resolve the remaining Windows-gate blockers, though. WINDOWS_EXCLUDED still removes all of orchestration.test.ts even though only its pool-duty section starts two daemons on one root, dropping substantial portable Windows coverage. It also still changes the two pre-existing Windows-only skill installation cases in skill-install-ledger.test.ts and skills-cli-golden.test.ts from live tests to unconditional it.skip after the real Windows run exposed EPIPE / confined-mutation failures. Because skill installation is part of the claimed supported Windows surface, the new gate should not become green by permanently hiding that functional failure; please fix the Windows path or keep the failure explicitly tracked and visible in CI. The Windows job for this revision is still pending.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

spacedragon and others added 2 commits August 26, 2026 19:18
Round 7: one file, three failures — `shim-skill-handler.test.ts`, which #1545 added
to main while this branch was converging. It is the sandbox-pod plane like every
other shim suite, so it joins that group; the comment now says a new suite over
that plane belongs there, since the ones absent from the list do pass on Windows.

Merges main, which brings #1535 — the same win32-only EACCES/EBUSY/EPERM rename
retry for workspace directory swaps that this branch added for the memory publish,
arrived at independently. The memory-side comment now points at it.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This revision is just a clean merge of origin/main (no conflicts in files this PR touches) plus one small follow-up commit: excluding the new test/shim-skill-handler.test.ts (added by the merged-in cluster-skills feature) from the Windows job. Checked it — it's genuinely part of the sandbox-pod plane (imports ClusterSkillHandler/ClusterSkillClient), so the exclusion is correctly scoped and consistent with the existing rationale. The memory/fs.ts comment update is accurate too (WorkspaceManager.renameWorkspaceDirectory does use the same bounded-retry pattern).

The three blockers from prior revisions are still open, untouched by this diff:

  1. test/orchestration.test.ts remains wholly excluded from the Windows job (vitest.config.ts:54) though only its duty-handoff cases need the shared-root carve-out.
  2. The O_NOFOLLOW-inert-on-Windows symlink-escape gap (memory/fs.ts, shim/*, skills/*) and the duty-gain inbox replay failure (daemon-duty-inbox-replay.test.ts) are still only "tracked separately" in comments with no linked issue.
  3. skill-install-ledger.test.ts/skills-cli-golden.test.ts still unconditionally it.skip the Windows skill-install case that fails with SkillLedgerSafetyError/EPIPE — a real functional gap, no linked issue.

Please resolve or link real tracking for these before merge.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-reviewed the exact a546c306 → 25355fa9 diff after the main merge. The merge resolution and the new shim-skill-handler.test.ts exclusion are coherent with that suite's Linux-only sandbox-pod role, and the memory retry comment is harmless. Two blocking coverage regressions remain against the new base: (1) WINDOWS_EXCLUDED still removes all of orchestration.test.ts, although its cases through startup re-arm use only one daemon and only the pool-duty section opens the same root twice; and (2) the two pre-existing Windows-only skill-install cases in skill-install-ledger.test.ts and skills-cli-golden.test.ts are still changed to unconditional it.skip after the real runner exposed EPIPE / confined-mutation failures. Since skill installation is part of the claimed Windows-supported surface, the gate should not become green by hiding those failures. Please scope the orchestration carve-out and repair or explicitly keep the Windows skill-install failure visible. The Windows job for this revision is still pending.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

…visible

The Windows job went green, and the review bot is right about how two of those
greens were bought.

`orchestration.test.ts` was excluded whole on the claim that every case opens a
root twice; only its `pool duty gate on deadlines` describe does. That describe now
carries the skip and the file is back in the Windows run — 18 portable cases with
it. The four `-pool` suites stay whole-file: each has exactly one describe, and it
is the pool one.

The two Windows-only skill-install cases become `it.fails` rather than `it.skip`.
Skill install is part of the supported Windows surface, so `write EPIPE` from the
gated helper has to stay visible: the marker fails the moment the gap is fixed,
which is the signal to remove it. A skip would just hide it.

`daemon-lifecycle`'s paused-session case is un-skipped — its comment described the
memory-publish rename race that `publishOverTarget` now retries, so it should run
on Windows and say so if it still cannot.

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

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three blockers I'd been carrying forward are resolved in this revision:

  1. orchestration.test.ts scoping — verified: the whole-file exclusion is gone from vitest.config.ts, and only the actual multi-daemon describe('pool duty gate on deadlines', ...) block (line 414 onward, the one with concurrent daemon/daemon2 on one root) is now describe.skipIf(win32). The other daemon2 usage at line 402 (startup re-arm) stops the first daemon before starting the second, so it's sequential, not concurrent — correctly left unskipped. The ~15 portable cases (subtask reporting, deadlines, cancel/ownership) are back on Windows CI.
  2. daemon-lifecycle.test.ts's it.skipIf — removed entirely; the publishOverTarget retry landed a few revisions ago actually fixed the underlying EPERM race, confirmed by the diff (pure un-skip, no logic change).
  3. Windows skill-install gapskill-install-ledger.test.ts and skills-cli-golden.test.ts switch from an invisible it.skip to it.fails, which keeps the known write EPIPE/SkillLedgerSafetyError failure visible in CI and will itself break (test passing when marked to fail) the moment someone fixes the underlying bug — a real improvement over a silent skip.

One small residual inconsistency, not blocking: the O_NOFOLLOW-inert-on-Windows symlink tests (memory.test.ts:148, memory-fs.test.ts:55, workspace-reader.test.ts:276) and the duty-gain inbox replay tests (daemon-duty-inbox-replay.test.ts) still use plain it.skipIf with "tracked separately" comments rather than the same it.fails visibility pattern just adopted for skill-install. Worth a follow-up for consistency, but doesn't block this PR's stated goal.

sent by review-bot-fast (Claude Agent · sonnet) · open in session

@agentconnect-md-test agentconnect-md-test Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two prior coverage blockers are fixed correctly: orchestration.test.ts is back in the Windows suite with only its pool-duty section skipped, and the lifecycle case also runs successfully. The current Windows job nevertheless fails because both newly changed it.fails cases now pass on the real runner. Vitest reports Error: Expect test to fail for skill-install-ledger.test.ts and skills-cli-golden.test.ts; the daemon summary is 4495 passed, 2 failed, and those are the only failures. This shows the presumed Windows skill-install gap is already resolved at this revision. Please restore both cases to ordinary it(...) tests and remove the stale failure comments. The CLI suite passed.

sent by review-bot (Codex · gpt-5.6-sol) · open in session

// `it.fails`, not skip: skill install IS supported on Windows and this gap must stay visible. The
// helper exits before its stdin write lands — `write EPIPE` from skill-workspace-mutator.ts. When
// that is fixed this case fails for passing, which is the signal to drop the marker.
it.fails(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exact Windows job shows this body succeeds, so it.fails itself produces Error: Expect test to fail and makes the new gate red. Restore this to an ordinary it(...) and remove the now-stale EPIPE comment.

// `it.fails`, not skip: the confined mutation path refuses its own bundle on Windows and that gap
// must stay visible. Same cause as skill-install-ledger's Windows case; fixing it fails this case
// for passing, which is the signal to drop the marker.
it.fails('runs the pinned CLI and publishes its receipt-verified bundle', async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case also succeeds on the real Windows runner; it.fails is one of the job's only two failures. Make it an ordinary it(...) test and remove the stale confined-mutation-gap comment.

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