Symptom
Five tests hit the 30s Bun global --timeout on Windows CI even though they mock Npm.install — no real package install, no real network.
| Test |
File:Line |
| installs dependencies in writable OPENCODE_CONFIG_DIR |
config.test.ts:781 |
| dedupes concurrent config dependency installs for the same dir |
config.test.ts:815 |
| serializes config dependency installs across dirs |
config.test.ts:873 |
| tool.registry > waits for config-scoped dependencies before importing local tools with bare imports |
registry.test.ts:160 |
| plugin.loader.shared > retries auto-discovered file plugins that reach config deps through helper imports |
loader-shared.test.ts:752 |
All five are bare test(...), not it.live / testEffect — so the helper-level scaling proposed in #14 does NOT reach them.
Evidence (last 5 Windows CI runs on dev, 2026-04-16 → 2026-04-17)
| Test |
Ubuntu pass |
Windows pass durations |
Windows fail |
Explicit timeout |
| installs dependencies in writable CONFIG_DIR |
11ms |
22828ms (1 pass across the sample) |
30015ms × 3 |
none (30s global) |
| dedupes concurrent config |
127ms |
391ms, 18891ms |
30016ms × 2 |
none |
| serializes config across dirs |
1ms (non-win32 early-return) |
Windows-only path, no pass observed |
30015ms × 1 |
none |
| tool.registry waits for config-scoped |
341ms |
2329ms, 28860ms |
30016ms × 1 |
none |
| plugin.loader retries auto-discovered |
20ms |
24375ms |
30015ms × 1 |
none |
Why this is weird
All 5 tests mock Npm.install — no real download, no child npm process. Ubuntu pass times are 11-341ms. Windows pass times are 18-29s.
That's a 100-3000× gap, and it's NOT Windows being slow at npm (npm isn't running). Candidates to investigate:
- Effect runtime setup cost (
Instance.provide, Layer construction) on Windows event loop
fs.mkdir / Filesystem.exists call latency on GitHub Actions Windows runner disk
- Child process spawn overhead from unrelated setup (tool loading, plugin resolution walking node_modules)
- Mock signal gates (
await gate, await ready, await waiting) deadlocking or yielding slowly under Windows scheduling
- Module resolution / first-import cost amortized onto the first test in the file
Root cause is unknown — needs local Windows reproduction or instrumented logging.
Treatment plan
Short term — stopgap PR (separate)
Add explicit { timeout: 60_000 } to each of the 5 tests with a // FIXME(#16) comment linking here. This unblocks CI while root cause is investigated.
Deliberately NOT raising the Bun global --timeout — we want future unrelated hangs to still fail fast at 30s.
Long term — this issue
- Reproduce at least one of the 5 hangs locally on Windows (or add
DEBUG-style timing logs and observe on CI).
- Instrument timing around suspect areas:
Instance.provide boundary, Config.get, Config.waitForDependencies, module import tree inside the mocked install callback.
- Identify what actually consumes 18-29s.
- Fix the root cause; remove stopgap explicit timeouts.
Related
Symptom
Five tests hit the 30s Bun global
--timeouton Windows CI even though they mockNpm.install— no real package install, no real network.All five are bare
test(...), notit.live/testEffect— so the helper-level scaling proposed in #14 does NOT reach them.Evidence (last 5 Windows CI runs on
dev, 2026-04-16 → 2026-04-17)Why this is weird
All 5 tests mock
Npm.install— no real download, no childnpmprocess. Ubuntu pass times are 11-341ms. Windows pass times are 18-29s.That's a 100-3000× gap, and it's NOT Windows being slow at npm (npm isn't running). Candidates to investigate:
Instance.provide, Layer construction) on Windows event loopfs.mkdir/Filesystem.existscall latency on GitHub Actions Windows runner diskawait gate,await ready,await waiting) deadlocking or yielding slowly under Windows schedulingRoot cause is unknown — needs local Windows reproduction or instrumented logging.
Treatment plan
Short term — stopgap PR (separate)
Add explicit
{ timeout: 60_000 }to each of the 5 tests with a// FIXME(#16)comment linking here. This unblocks CI while root cause is investigated.Deliberately NOT raising the Bun global
--timeout— we want future unrelated hangs to still fail fast at 30s.Long term — this issue
DEBUG-style timing logs and observe on CI).Instance.provideboundary,Config.get,Config.waitForDependencies, module import tree inside the mocked install callback.Related
OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER=truefor Windows; this bucket persists past that fix.it.live3s ceiling): chore(ci): remove dead upstream publish.yml workflow #14 — different root cause (real-clock runner slowness), different fix.