Repository navigation
Plural Electron: scope desktop dev to the worktree - #664
Merged
Merged
Conversation
added 5 commits
July 31, 2026 06:48
0404 wired the desktop prototyping loop for a single seat. This documents what is still asymmetric versus the web loop: the Electron dev environment is a machine-wide singleton (one SingletonLock, one userData, fixed 5177/9223) while the repo is worked across 87 git worktrees. Recommends deriving the profile and a ten-port block from the worktree, publishing provenance on window.__xnetDev, bridging main and data-process logs into the renderer console, and making port/lock collisions loud. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
Electron dev was a machine-wide singleton — one SingletonLock, one userData, hard-coded 5177/9223/4444/31415 — while the repo is worked across dozens of git worktrees. The second `pnpm dev` lost the lock, called app.quit(), and exited 0; an agent then attached to :9223 and drove whichever instance already owned it, usually a different branch. Every step succeeded and the verification was false. - Derive profile `wt-<worktree>` and a ten-port block (20000 + offset*10) from the linked worktree, resolved once in the dev launcher and passed down as XNET_DEV_SCOPE. The main checkout keeps `default` and its legacy ports. - Publish provenance on `window.__xnetDev` (worktree, branch, commit, ports, pid), dev-only, and name the instance in the title bar for every profile. - Forward main and data-process logs into the renderer console through a bounded ring buffer, so a CDP-attached agent sees all three processes and boot failures survive until a window exists. - Fail loudly: strictPort on the renderer, a named error plus exit(1) on lock loss, and a CDP identity assertion that refuses to report ready when the port is serving someone else's renderer. - Add `dev:clean` to prune profiles whose worktree is gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
The port tables in apps/electron/AGENTS.md and the electron-prototype skill
became wrong the moment ports started being derived per worktree, and the
skill's "confirm which instance you attached to — the profile name in the title
bar is the cheapest signal" was never followable: the title was plain `xNet`
for the `default` profile, so a stale instance and your own were identical in
exactly the case worth catching.
Replaces both with the derivation rule, the `[xnet-dev] ready {…}` line to wait
for, and `window.__xnetDev` as the authoritative answer to "which tree is
this?". Drops the hand-cut `electron-renderer-worktree (vite 5178)` launch
entry, which existed because there was only ever one worktree seat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
The `title` option on BrowserWindow is only the *initial* title — Electron discards it as soon as the document declares its own `<title>`, and renderer/index.html does. So the profile label added for 0413 never actually reached the window: verified titles still read plain `xNet`. Own the title in development via `page-title-updated`, which also survives the renderer updating it later. `document.title` is deliberately left alone — CanvasView reads it to name captured content. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
…d desktop dev 25 of 26 items. Records the measured results against a live pair of instances — the user's main-checkout app was running throughout, so the CDP collision the exploration is about was reproduced and then caught rather than simulated. Also notes three defects found by building it (stableProfileOffset could not be reused; git hook variables corrupted worktree detection; the window title option was inert) and one left alone (rebuild-if-stale's stamp does not notice `pnpm install --force` replacing the native binary). The remaining item — recording turns-to-prototype, desktop versus web — is a measurement activity across future work, not a change this PR can contain. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
Contributor
|
Preview removed for PR #664. |
The first version resolved against the running checkout, so it asserted a property of the machine rather than of the code: it passed locally (a linked worktree) and failed in CI (a plain clone), and it hard-coded absolute paths from one developer's disk. Build both shapes in a temp directory instead — a plain checkout and a real `git worktree add` of it — so the same assertions hold anywhere git exists. The setup helper scrubs GIT_* for the same reason the resolver does: under a git hook those variables are exported and its `git commit` operated on the hook's repository instead of the temp one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: xNet Test <test@xnet.dev>
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements exploration 0413 — 25/26 items.
The bug
Electron dev was a machine-wide singleton: one
SingletonLock, oneuserData, hard-coded 5177/9223/4444/31415. This repo is worked across 87 git worktrees, 41 of them agent worktrees.So the second
pnpm devlost the lock, calledapp.quit(), and exited 0. An agent read that as success, attachedplaywright-electronto:9223, and drove whichever instance already owned the port — usually a different branch. Every step succeeded; the verification was false. The documented mitigation ("check the profile name in the title bar") could not work: the title was plainxNetfor thedefaultprofile, so the incumbent and the newcomer were identical in exactly the case worth catching.The fix
wt-<worktree>and a ten-port block (20000 + hash(path) % 500 * 10) derived from the linked worktree, resolved once inscripts/dev-launch.mjsand passed down asXNET_DEV_SCOPE. The main checkout is unchanged —default, legacy ports — so nothing pre-existing moves. Because Chromium keys the lock onuserData, each worktree gets its own lock for free.window.__xnetDev(worktree, branch, commit, profile, ports, pid), dev-only, read through the tool an agent already has. The window title names the profile and commit for every profile.[main]/[data], through a bounded ring buffer so failures from before the window existed survive —window.__xnetDev.logs().strictPorton the renderer; lock loss → named error +exit(1); a CDP identity assertion that refuses to report ready when the port serves another tree's renderer.Verified against a live collision
The main checkout's dev app was running throughout, so this is the real thing, not a simulation.
main)default…local-32967wt-agentic-…-74b20c…local-16919Both alive at once — the thing that was impossible before.
Gates:
pnpm test11,426 passed / 1,121 files ·turbo run typecheck40/40 uncached ·check:electron-parityOK.Three defects found by building it
stableProfileOffset()could not be reused as the doc proposed — its numeric-suffix branch collapses every worktree slug ending in a hex digit onto the same offset. Worktrees use FNV-1a over the whole path.GIT_DIR/GIT_WORK_TREE, which leak intogitsubprocesses and made a main-checkout commit resolve as a linked worktree.git()now scrubsGIT_*; regression test included.BrowserWindow'stitleoption is inert once the document declares<title>— the label is now owned viapage-title-updated.Not done
rebuild-if-stale.mjs(0404) does not noticepnpm install --forcereplacing the native binary, so its stamp can stay warm over a wrong-ABI module. Flagged in the doc as a follow-up.🤖 Generated with Claude Code