Use the NUCLEIC_-prefixed binding names consistently across wrangler.jsonc, the
worker code (env.ts/index.ts/room.ts), and docs (README, CLOUD_INFRA), so the
declared KV bindings match what the Worker reads at runtime.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Squash-merge nucleic/trunk into dev (234 commits of accumulated nvrsion work).
Resolved two auto-generated-file conflicts:
- cloud/nucleic-edge/wrangler.jsonc: kept dev's real KV namespace ids and the
xyz.blakeslee.nucleic.remote APNS topic, with binding names corrected to
RELAY_TOKENS/PUSH_TOKENS to match the worker code on both branches.
- Package.resolved: took trunk's newer dependency pins.
Nucleic-Promote: 1
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Desktop channels → xyz.blakeslee.nucleic.desktop.{dev,beta,rc,release} (the stable channel keyword is unchanged; only its bundle-id suffix is "release"). iOS remote → xyz.blakeslee.nucleic.remote, including its Keychain account namespaces, the scanner log subsystem, and the coupled APNS topic.
Correct the Apple Developer Team ID to L7UDTQ6F5W across the Xcode project, ExportOptions, the APNS config + tests, and the signing/cloud docs.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Add an app-wide nvrsion toggle to Settings -> Control (nvrsionByDefault), which seeds
new Nucleic Control projects with nvrsion on; mirrors controlByDefault/sandboxByDefault.
- Clean up the per-project card copy (title 'nvrsion'; new description) and fix Project
Settings descriptions truncating, by giving each Toggle label .fixedSize so it wraps.
- Make a session's versioning mode fixed at creation (isNvrsionSession = 'its working dir
is the trunk') instead of re-derived from the project's current toggle. lockDomain and the
land/re-ground path key off that, so existing chats keep their mode after a flip and the two
models never mix. Removes the flip-safety guard, which wrongly blocked the toggle whenever an
idle ('complete', awaitingInput) chat existed.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
An opt-in (Beta, Nucleic-Control-only) versioning mode where a project's agent
sessions share one nucleic/trunk checkout, lock individual files per-edit, land each
completed edit into the trunk immediately, and release fast — instead of holding a
session-long lock until a big merge. Conflicts are structurally impossible within the
trunk (serialized per-file writes + forced re-ground), so 'merge' collapses to 'commit'.
- Phase A: ProjectNvrsion config, migration v20-nvrsion, nvrsionActive gate, Beta toggle
- Phase B: NvrsionTrunk actor (ensureTrunk/land/regroundOnGrant), shared-trunk topology
(no per-session worktree), per-edit host-mediated path-scoped commit + release
- Phase C: NvrsionReleaseGovernor keep-warm idle eviction, launch crash-recovery,
flip-safety guard
- Phase D: pre-land validation hook, trunk->base squash promotion + 'Promote trunk' UI
Design and rationale: docs/NVRSION.md. Full suite green (585 tests).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Reflect the promotion in VSOCK_CONTROL_PLANE.md: the control plane rides the vsock-relayed socket by
default as of sandbox image v4, legacy gateway-TCP is the fallback behind an explicit off switch.
Also documents the Grok-install fix (relocated to /opt/grok) and the now-bounded MCP_TIMEOUT.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
CodexExecBackend now execs codex exec inside its control container (stdio over vsock) on the vsock control-plane path, with the git/gh/command interceptor wired to the shared per-container server (observe/release -> conflictCoordinator). --ask-for-approval never means no interactive acquire seam, so it joins the lock system on observe/release only. resume() now carries the container through. Gated on the control socket; default behavior unchanged.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
CodexAppServerBackend now joins conflict locks, like Claude/Grok.
Acquire: an item/fileChange/requestApproval arbitrates on the edited paths before the patch applies (deny on deferred/cancelled/re-ground, ahead of the always-rule cache so an 'always allow' can't slip a conflicting edit past). The approval carries only the item id, so paths are captured from the fileChange item lifecycle (CodexAppServerDecoder.fileChangeItemPaths).
Release/observe: the same shared per-container server + git/gh/command interceptor wiring as Grok. Codex's approvals stay native (no MCP), so only the report routes register.
Gated on the vsock control socket, so default behavior is unchanged. CodexExecBackend (unattended, no interactive approval seam) is left unchanged.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
GrokACPBackend resolves the shared per-container approval server, starts it on the relayed control socket, registers the git/gh/command report handlers (-> conflictCoordinator: locks + autoship), and injects CommandInterceptor.hookEnv. Grok's approvals stay native ACP (no MCP), so only the report routes register. Gated on the vsock control socket like the exec path, so default behavior is unchanged. Brings Grok control containers to parity with Claude (isolation + git observation). Refreshes the stale host-only comments + docs.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Codex via npm (@openai/codex); Grok via the official x.ai installer, symlinked onto the global PATH with a grok --version build check that fails loudly if the arm64 binary didn't land.
containerSpec() now seeds auth per backend: both store auth as plain files (no Keychain), so seedAgentHome copies the host's ~/.codex / ~/.grok into the per-session writable home (the agent's $HOME), where the CLIs find $HOME/.codex / $HOME/.grok automatically. API-key users are covered by forwarding OPENAI_API_KEY / XAI_API_KEY / GROK_CODE_XAI_API_KEY.
Completes the binaries + auth for the gated Grok/Codex control-container exec path. See docs/VSOCK_CONTROL_PLANE.md.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Run a Nucleic Control container's approval + interceptor channel over a vsock-relayed unix socket instead of TCP/HTTP on the VM gateway, so macOS raises no incoming-connection / local-network prompts.
- MCPApprovalServer: real AF_UNIX listener + transport-agnostic ByteConn (host UDS transport).
- ContainerEngine: relay the host control socket into the guest (UnixSocketConfiguration.into); init launches an in-guest loopback bridge (control-bridge.js) forwarding 127.0.0.1:9099 -> the relayed socket.
- ApprovalServerRegistry: one token-multiplexed approval server per shared control container.
- ClaudeCodeBackend: serve UDS-only (no IP listener) + point mcpConfig/interceptor env at the bridge; CommandInterceptor.hookEnv centralizes the interceptor wiring.
- GrokACPBackend / CodexAppServerBackend: exec inside the shared control container (stdio over vsock) for per-family isolation.
All gated behind ContainerServiceSettings.vsockControlPlaneEnabled (default off); legacy gateway-TCP path unchanged. Needs the sandbox image to ship control-bridge.js (and, for Grok/Codex, their CLIs + auth) before flipping the flag. See docs/VSOCK_CONTROL_PLANE.md.
Co-Authored-By: Claude Opus 4.8 <[email protected]>