Skip to content

fix(test): isolate service state from the shared startup home - #7161

Merged
lidge-jun merged 3 commits into
devfrom
fix/service-state-test-isolation
Oct 15, 2026
Merged

lidge-jun merged 3 commits into
devfrom
fix/service-state-test-isolation

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Summary

Parallel bun test workers all share one startup home. Bun caches os.homedir() at process start, so the preload's per-worker HOME never reaches it, and service-state's legacy default-home mirror (<startup home>/.opencodex/service-state.json) was shared by every worker and by serial cases that switch OPENCODEX_HOME fixtures. A foreign record left there broke service SQLite-home binding and diagnostics tests depending on file order.

  • Under the armed test-home guard, src/service/state.ts resolves service-state reads and writes only within the selected OPENCODEX_HOME, including captured-home lookups. The existing real-home filter stays. Production keeps its mirror writes and legacy migration reads unchanged.
  • tests/service/service-state-isolation.test.ts plants a foreign startup-home record in a child process, moves HOME the way the preload does, and checks isolated reads, writes, and a fixture switch with the guard armed, plus unchanged mirror behavior with it disarmed. The boundary is documented in structure/ops/test-sandbox-cleanup.md and structure/runtime.md.

Why a guarded branch in state.ts and not a per-worker HOME in the runner. On Bun 1.4.3, homedir() keeps the startup value after process.env.HOME changes, and replacing os.homedir from a preload does not reach named import { homedir } bindings (verified directly). Bun spawns --parallel workers itself, so scripts/test.ts has no per-worker spawn hook. Giving each worker its own HOME would mean replacing Bun's worker pool with runner-owned sharding. That is a much larger change, and it would still miss serial cases inside one worker that switch fixtures. The guarded branch also extends an existing precedent: serviceStatePaths() already dropped the mirror under the guard when it named the real home.

Other homedir() consumers were surveyed. Most are read-only probes, accept an injected home, or already prefer process.env.HOME (claude/gateway-cache.ts). The one with the same shape is the owner registry (<homedir>/.opencodex/ocx-homes). Its OCX_OWNER_REGISTRY_DIR seam is set by the suites that use it, and no failure points at it, so it is left as a follow-up.

Verification

  • Regression reproduced before the fix: the guarded child read the planted foreign record. After the fix it reads no foreign state and leaves the planted record unchanged.
  • Service suites (service-state-isolation, service-sqlite-home, service, service-ownership-state, ci-workflows/test-home-guard): 290 pass, 0 fail serially and with --parallel=4.
  • Layout and ratchet guards (test-layout, test-layout-tooling, file-size-ratchet): 36 pass. bun run typecheck, bun run structure:check and bun run privacy:scan pass.
  • bun run test:changed: 30,198 pass, 68 skip, 5 fail, 4 unhandled errors across 1,350 files, all in three CLI files. To attribute them, bun scripts/test.ts --parallel=1 on tests/cli/cli-access-audio-live.test.ts, tests/cli/cli-headless-parity.test.ts and tests/cli/sibling-home-client-sync.test.ts was repeated on this head and on a clean origin/dev (7640a942b) worktree. Both trees fail the same cases every round: the three live audio readiness 5s timeouts and the 30s secondary ensure parent preserves shared Grok, Codex and Claude agent bytes timeout (165/4 here; 165/4 and 166/3 on dev). They are pre-existing. cli-headless-parity, the source of the earlier varying combo and Raycast assertions, passed on every run in both trees. The Raycast failure body read auth required, which appears nowhere in src/ and which the test's fake server never sends, so a foreign local listener answered on that port during a load spike. Neither touches service state.
  • The full local suite was not run: five other worktrees were running test:changed concurrently (load average above 40). Broader and non-macOS coverage is left to the manual ci.yml dispatch with lane=all on head f5ccb650d, queued behind a repository-wide Actions backlog. This PR stays draft until it completes green.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults. The protected-real-home filter remains enforced; production path selection is covered by the regression.

@coderabbitai

coderabbitai Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Oct 15, 2026
…-isolation

# Conflicts:
#	scripts/test-layout/layout.json
# Conflicts:
#	scripts/test-layout/layout.json
#	structure/ops/test-sandbox-cleanup.md
#	tests/fixtures/test-layout-expected.json
@lidge-jun

Copy link
Copy Markdown
Owner Author

Maintainer integration into dev (MAINTAINERS.md dev maintainer-integration policy; batch integration authorized by @lidge-jun on 2026-10-15).

  • Head: d32f6708bd40480e15b19d1ca447a24c0aaf0643 (tree 4f084fd046c9caf2fe63d312c59a723c54479e89) = this branch merged with origin/dev 2cd40297e1.
  • Exact-head evidence: GitHub-hosted Actions for this account have not been assigning runners since 2026-10-15 13:30 UTC, so by owner decision the evidence is a full bun run test (Bun 1.4.3 test runner, root and GUI dependencies installed, GUI built) of this exact tree on a maintainer host (Linux x86_64): exit 1, 7 min, 31 failing test(s), each also failing in the same host's baseline run of dev 60bf4c7 (environment-only): Codex shim install readiness > a refused install exits unsuccessfully and preserves its re, Codex shim install readiness > keeps install advisory when the Codex config cannot be read, Codex shim install readiness > the install command surfaces readiness warnings without lea, GUI pairing client > sends one bodyless origin-bound capability and redacts rejected bodie, Node launcher PATH fallback activation > broken bundle reaches validated PATH Bun, Node launcher PATH fallback activation > inspection bundle reaches validated PATH Bun, Node launcher PATH fallback activation > missing bundle reaches validated PATH Bun, a secondary ensure parent preserves shared Grok, Codex and Claude agent bytes, ….
  • Local gates on the same tree: bun run typecheck, file-size ratchet, test-layout and structure:check.
  • Hosted CI checks for this head may still be queued; they are not claimed as evidence.

@lidge-jun
lidge-jun marked this pull request as ready for review October 15, 2026 18:25
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 15, 2026 18:25
@lidge-jun
lidge-jun merged commit ae95f2d into dev Oct 15, 2026
6 of 7 checks passed
@lidge-jun
lidge-jun deleted the fix/service-state-test-isolation branch October 15, 2026 18:25
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T18:28:07.358976Z d32f670 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant