Skip to content

test(claude): isolate the Desktop lifecycle lock in first-party fixtures - #7868

Merged
lidge-jun merged 1 commit into
devfrom
fix/first-party-lifecycle-lock
Oct 28, 2026
Merged

lidge-jun merged 1 commit into
devfrom
fix/first-party-lifecycle-lock

Conversation

@lidge-jun

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

Copy link
Copy Markdown
Owner

Summary

tests/claude-integration/claude-desktop-first-party.test.ts > POST /api/claude-desktop/apply defaults to gateway; first-party is explicit and carries the account-risk notice failed in #7760's test changed job (run 40626448565, job 122613979078, ubuntu) with HTTP 500 and {"error":"desktop_lifecycle_busy_or_unsafe","saved":true}. #7760 does not touch that path.

Cause: Claude Desktop writes run under the client lifecycle lock (src/client/lifecycle-lock.ts). Unless a caller passes lockPath, that lock lives in the effective OS user's runtime directory, independent of OPENCODEX_HOME, and it is taken with busy_timeout = 0. CI runs test files in parallel processes as one user. Whenever another file held that lock, this file's gateway apply got client_lifecycle_busy, which writeDesktop3pConfig (src/claude/desktop-3p.ts) reports as desktop_lifecycle_busy_or_unsafe. The product refusal is correct; the fixture was not isolated. Other files already isolate it, for example claude-desktop-picker-profile.test.ts and claude-desktop-cli.test.ts.

Changes (tests only):

  • New tests/helpers/client-lifecycle-lock.ts wraps the sync and async lifecycle entry points with lockPath: deps?.lockPath ?? <fixture>/locks/lifecycle.sqlite and forwards to the real implementations, so SQLite exclusion and lease checks stay real. Explicit lock paths are preserved.
  • The helper is installed in beforeEach and restored in afterEach in this file and in the seven sibling files that reach the same writers in process: claude-desktop-first-party-guards, claude-desktop-picker-routes, claude-first-party-agent-sync, claude-config-root-writer-barrier, claude-config-root-late-admission, claude-intercept-acl-barrier and claude-messages-endpoint.
  • New regression: gateway and first-party apply through the real management route must succeed, must acquire the lifecycle lock, and must resolve every acquisition beneath the fixture root. A sentinel fails the test before the production namespace could be opened, so the test never touches a real user's lock.

No production code, timeouts, retries, skips or assertion changes.

Verification

Windows 11, Bun 1.4.4:

  • claude-desktop-first-party.test.ts: 15 pass / 23 fail on clean origin/dev on this host (Windows host baseline), 39 pass / 0 fail with this change.
  • New regression: fails (500 refusal) with the helper's lockPath removed, passes with it.
  • Local contention probe (not committed): with a controlled scratch lock database held in BEGIN IMMEDIATE, the unisolated gateway apply returned 500 desktop_lifecycle_busy_or_unsafe (underlying client_lifecycle_busy). The isolated gateway and first-party applies returned 200 while that transaction was still held.
  • The seven sibling files: 195 pass / 3 fail. Two of the failures (an explicit picker off is remembered... timeout, present invalid compatibility modes return one fixed 503...) also fail on clean origin/dev on this host. The third (native passthrough precedes even invalid compatibility mode, SPEND_LEDGER_OWNER_HOME_CONFLICT) followed the preceding timed-out cleanup and was not separately reproduced on the baseline.
  • File-size ratchet and layout guards: 38 pass / 0 fail. bun run typecheck: exit 0.

NOT RUN: full bun run test, local test:changed, hosted macOS/Windows CI. Ubuntu PR CI covers the hosted Linux job where this failed.

Checklist

  • Targets dev
  • Regression test added
  • No retries, longer timeouts, skips or weaker assertions
  • No GUI change

Summary by CodeRabbit

  • Tests
    • Improved isolation across Claude integration tests by keeping temporary test environments’ lifecycle locks separate and restoring test state during cleanup.
    • Added coverage confirming management operations keep lock files within the test environment and do not resolve production runtime paths.
    • No end-user functionality changes.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 28, 2026 04:27
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 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-28T04:29:04.809598Z 738b595 PR opened
ℹ️ 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.

@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Oct 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • missing_coauthor_credit — This pull request says it reimplements, supersedes, carries, or rebases another author's pull request, but no Co-authored-by trailer names that author. Prose in a commit body is not read by anything; the trailer is what GitHub counts. Add it to the description or a commit, or obtain attribution-approved. Paths: #7760.

@github-actions github-actions Bot added the chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). label Oct 28, 2026
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed.

Hygiene

✅ Deterministic PR hygiene checks passed.

@github-actions
github-actions Bot marked this pull request as draft October 28, 2026 04:28
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 713fdfb and 738b595.

Files selected for processing: 9
  • tests/claude-integration/claude-config-root-late-admission.test.ts
  • tests/claude-integration/claude-config-root-writer-barrier.test.ts
  • tests/claude-integration/claude-desktop-first-party-guards.test.ts
  • tests/claude-integration/claude-desktop-first-party.test.ts
  • tests/claude-integration/claude-desktop-picker-routes.test.ts
  • tests/claude-integration/claude-first-party-agent-sync.test.ts
  • tests/claude-integration/claude-intercept-acl-barrier.test.ts
  • tests/claude-integration/claude-messages-endpoint.test.ts
  • tests/helpers/client-lifecycle-lock.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

Walkthrough

Claude integration tests now isolate client lifecycle locks under temporary roots and restore the lock spies during teardown. A management API test checks that acquired lock paths remain within the fixture root and that production runtime-root resolution is not called.

Changes: Claude integration test lock isolation

Layer / File(s) Summary
Lifecycle-lock isolation helper
tests/helpers/client-lifecycle-lock.ts
Adds a helper that wraps synchronous and asynchronous lifecycle-lock calls, uses a root-scoped default path when no path is supplied, records acquisition kinds and resolved paths, and restores both spies.
Fixture isolation and management API verification
tests/claude-integration/claude-config-root-late-admission.test.ts, tests/claude-integration/claude-config-root-writer-barrier.test.ts, tests/claude-integration/claude-desktop-first-party-guards.test.ts, tests/claude-integration/claude-desktop-first-party.test.ts, tests/claude-integration/claude-desktop-picker-routes.test.ts, tests/claude-integration/claude-first-party-agent-sync.test.ts, tests/claude-integration/claude-intercept-acl-barrier.test.ts, tests/claude-integration/claude-messages-endpoint.test.ts
The fixtures isolate lifecycle locks using their temporary roots and restore the spies during teardown. The management API test checks lock-path containment and confirms that production runtime-root resolution is not called.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Merge Risk: Minimal · up to 738b5

The fixtures use isolated lock paths. No merge-blocking issue was identified.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: isolating the Claude Desktop lifecycle lock in first-party test fixtures.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 9 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • 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 github-actions Bot removed the intake: hygiene-blocked Deterministic PR hygiene checks failed label Oct 28, 2026
@github-actions
github-actions Bot marked this pull request as ready for review October 28, 2026 04:31
@lidge-jun

Copy link
Copy Markdown
Owner Author

Maintainer integration into dev: all 26 checks passed on exact head 738b595, which merges into current origin/dev without conflict. Test-only change. Independent review (GPT-6.1 Sol, high) confirmed the isolation intercepts named imports for both sync and async lifecycle entry points, restores after failure, and that the namespace regression is non-vacuous; it also found two more files (claude-picker-runtime, claude-picker-relay-intent) that still reach the account-wide lock. That finding is accepted and will land as a follow-up PR from a full sentinel sweep, so this fix is not held for it.

@lidge-jun
lidge-jun merged commit 86b8216 into dev Oct 28, 2026
36 of 38 checks passed
@lidge-jun
lidge-jun deleted the fix/first-party-lifecycle-lock branch October 28, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant