Skip to content

install.spec.ts: non-deterministic parallel-worker isolation flake (installState module cache survives resetMocks) #412

Description

@obrien-k

Symptom

Under the full parallel unit run (npm run test), src/install.spec.ts intermittently fails ~14 assertions — POST /api/install returns 400 where the test expects 201:

● POST /api/install › seeds the flagship community owned by the SysOp
  expect(received).toBe(expected) // Object.is equality
  Expected: 201
  Received: 400
    at src/install.spec.ts:410:24

It is non-deterministic: it depends on Jest worker scheduling. Observed once during the v0.8.2 release gate; did not reproduce on an immediate re-run of the same tree, nor on the clean pre-release tree (both 1976/1976).

Reproduction

  • Fails: occasionally under npm run test -- --no-coverage (full suite, maxWorkers 50%)
  • Passes: always in isolation — npm run test -- src/install.spec.ts → 16/16

Isolation-pass + full-run-fail is the signature of shared cross-suite state, not a logic bug in install.

Root-cause hypothesis

modules/installState.ts keeps an in-memory module-level cache for isInstalled(). jest.config.cjs sets resetMocks: true, which clears mock fns between tests but does not reset module-level state (that needs resetModules). When another suite exercising the install path runs first on the same worker, it populates the isInstalled() cache to true; install.spec.ts then sees "already installed" and the handler short-circuits to 400 before reaching the seed path the test asserts on.

Suggested fix (root cause, not a retry)

Reset the installState cache in install.spec.ts's beforeEach (export a test-only cache-reset/invalidator from installState.ts, or jest.resetModules() + re-require), so the suite doesn't inherit another suite's install state regardless of worker ordering. Confirm no other suite mutates the cache without cleanup.

Impact

Test-only flakiness — no runtime/product impact. Surfaced by the v0.8.2 release gate (#411). Filed so a green local suite isn't a coin-flip.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Sonnet-5Dispatch to Sonnet 5 — bounded, pattern-following, gate-coveredbugSomething isn't workingready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions