feat(desktop): name the dev-profile lock holder in conflict messages - #3953
feat(desktop): name the dev-profile lock holder in conflict messages#3953rbalachandar wants to merge 2 commits into
Conversation
|
I reviewed this PR at exact head Standards: NO-GO — 1×P1 + 1×P2 + 2×P3
Other checks: branch/title conform, Spec: NO-GO — 3×P2 + 1×P3
No missing macOS loser surface was sustained; atomic reservation/handshake remains intentionally outside this naming scope. Other checks: core 665/665 PASS, launcher 25/25 PASS, format 1690 PASS, changed-file Biome PASS; What I did not check: full local Desktop suite beyond the checks noted. Gate: exact head has P1/P2/P3 findings in both axes and a failing required
|
Closes the observability half of the shared 'Maka Dev' profile launch race (apache#3539). When a launch loses the single-instance lock, the loser surfaces named the conflict only generically. Resolve the holder from Chromium's own SingletonLock record (a <hostname>-<pid> symlink target in the user-data dir), never from the process table: the symlink alone is not evidence — it survives SIGKILL — so a holder is reported only while its PID is still alive (kill(pid, 0), EPERM counts as alive), and a hostname mismatch is reported as another machine for shared homes. - packages/core/dev-single-instance-owner: parse + liveness + describe, undefined on any inconsistency so every caller degrades to the existing generic wording. - All three loser surfaces name the holder: the main-process loser dialog, the absorbed outcome in dev.mjs / start-dev-app.mjs, and the plain-loser stderr in dev-app-runtime.mjs. An explicit --user-data-dir wins over the shared default, matching launch behavior. The message is hedged ("appears to be"), which also covers the inherent PID-reuse race. The race's atomic-reservation half stays open. Generated-by: Claude Code
…form default, core purity Review follow-up on apache#3953. - Classify the hostname FIRST and probe liveness only for records written by this machine: a remote hostname was previously validated against the local process table, dropping valid shared-home records or blessing an unrelated local PID as a live remote holder. A missing local hostname now degrades instead of guessing. - Parse only the bare <hostname>-<pid> lock record. Path-shaped targets are rejected outright instead of being widened into plausible owners; the test that blessed that widening is inverted. - The scripts' default profile dir is platform-aware (macOS application support, Linux XDG config) and null on Windows, where no POSIX SingletonLock exists — the plain-loser detail degrades before any module load instead of inspecting a macOS path on other platforms. - Move the OS effects out of packages/core: the core module now only parses and classifies records (zero node imports), while the symlink read and PID liveness probe live in Desktop — a main-process resolver module and the launcher script's own effects. apache#3539's architecture keeps core as pure contracts. - Reverts the prompt-rail assertion loosening (ef13913): it weakened apache#3121 coverage, added trailing whitespace, and did not fix the hosted failure. Generated-by: Claude Code
ef13913 to
6af4d8c
Compare
|
Addressed the review findings; new head is
Verification on One semantic to confirm: a remote-host record is now reported as the holder ("appears to be PID N on host X") without liveness verification, since the owner machine cannot be probed locally — a stale remote symlink can therefore be named. If the stricter reading of "degrade inconsistent data" is preferred (drop unverifiable remote records), that's a one-line change plus a test flip; happy to switch either way. |
Summary
Refs #3539 (follow-up to #3359's shared 'Maka Dev' profile owner gate). When a launch loses the single-instance lock, all three loser surfaces — the main-process loser dialog, the absorbed outcome in
dev.mjs/start-dev-app.mjs, and the plain-loser stderr indev-app-runtime.mjs— named the conflict only generically.This resolves the holder from Chromium's own
SingletonLockrecord (a<hostname>-<pid>symlink target in the user-data dir), never from the process table:kill(pid, 0), withEPERMcounted as alive).undefined, and every caller falls back to the existing generic wording.--user-data-dirwins over the shared default, matching launch behavior.New
packages/core/dev-single-instance-owner(parse + liveness probe + describe), exported via the package map and lazy-loaded by the launcher scripts.This covers the "surface the actual owner" half of the issue's post-spawn handshake option; the atomic-reservation half remains open.
Verification
npm run build— passpackages/coresuite: 665/665apps/desktopsuite (dist/main+dev-app-runtimescripts): 1577/1577 stable run;dev-app-runtime.test.mjs25/25 including the five new conflict-detail testsnpm run lint,npm run format:check,npm run typecheck— pass (exit 0)AI use
Select exactly one:
Tool(s) and scope: Claude Code — implementation review, rebase onto current main, verification runs; human contributor of record reviewed and owns the change.
Checklist
Does this PR entail a change in behavior?