Skip to content

fix(restore): simplify persistence and harden cross-platform cleanup#602

Merged
shantur merged 24 commits into
NeuralNomadsAI:devfrom
pascalandr:fix/restore-followup-578
Jul 17, 2026
Merged

fix(restore): simplify persistence and harden cross-platform cleanup#602
shantur merged 24 commits into
NeuralNomadsAI:devfrom
pascalandr:fix/restore-followup-578

Conversation

@pascalandr

@pascalandr pascalandr commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Follow up feat(desktop): persist and restore UI state across restarts #578 by consolidating desktop persistence, restore reconciliation, lifecycle coordination, and regression coverage.
  • Preserve active drafts and attachments, request-scoped workspace ownership, deletion tombstones, renderer authority, and bounded shutdown behavior.
  • Fix the reported macOS cleanup failure with targeted BSD process queries and random-token-guarded process-group cleanup, without an unverified PID fallback.

Platform hardening

  • Ignore development renderer origins in packaged Electron builds.
  • Preserve staged Tauri navigation authority and handle confirmed Windows session-end shutdown on the UI thread.
  • Bound workspace launch preflight, runtime startup, and health readiness.
  • Retain cleanup ownership after unexpected leaders exit and verify portable POSIX descendants by immutable identity or inherited launch token.
  • Add real Darwin-only process-group integration tests for macOS CI.

Scope

  • 96 files changed.
  • 6,295 additions and 12,167 deletions, a net reduction of 5,872 lines from the merged implementation.
  • Consolidated duplicated tests while retaining focused race, durability, cleanup, and platform contracts.

Validation

  • pm run typecheck
  • pm run typecheck --workspace @neuralnomads/codenomad
  • Electron native suite: 60 passed
  • Tauri suite: 49 passed
  • Focused server lifecycle/identity suite: 31 passed, 2 Darwin-only skipped on Windows
  • Focused UI restore/codec/reconciliation suite: 36 passed
  • Broader server suite: 59 passed, 3 platform skips
  • Broader UI suite: 97 passed, 1 skip; 2 Node 25 solid-toast loader failures reproduced on the merged baseline
  • git diff --check
  • Final limited gatekeeper: PASS for server/macOS, UI restore, and Electron/Tauri

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29415142365

Artifacts expire in 7 days.
Artifacts:

  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-macos
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-macos-arm64
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-windows
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-linux
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-electron-macos
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-electron-linux
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29416879658

Artifacts expire in 7 days.
Artifacts:

  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-macos
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-windows
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-electron-macos
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-macos-arm64
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-tauri-linux
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-electron-linux
  • pr-602-1cfcd6f4de36239c6caa7c2e62ddb19679c24175-electron-windows

@pascalandr

pascalandr commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Gatekeeper review: BLOCK

Reviewed the entire PR #602 at head e986a246 against origin/dev: 104 files, 2 commits, 6,887 additions and 12,233 deletions. This is not a latest-commit-only review.

Blocking findings

  1. High: cache eviction can leave a session permanently empty. packages/ui/src/components/instance/shell/useSessionCache.ts clears an evicted session with notifications disabled. That prevents messagesLoaded invalidation, so returning to an evicted session can skip refetching its history.

  2. High: a workspace explicitly closed during startup restore can be resurrected. Late hydration success/failure can overwrite the preservation result from removed back to pending in use-app-session-restore.ts / app-session-snapshot-merge.ts. The same interval permits restore ownership release to race user-close cancellation. A failed first cancellation can also be reported as successful on retry while the workspace remains.

  3. High: Electron shutdown can orphan CLI or workspace processes. Electron escalates before the server cleanup budget for legitimate detached workspaces expires, and the ordinary lifecycle can advance after an unconfirmed Windows taskkill. On POSIX, killing the server group early does not clean workspace runtimes launched in separate detached groups.

  4. High: Electron/Tauri cross-host ownership is not a real bidirectional election. The current Electron-only Tauri PID-marker probe is asymmetric, has a check-to-election race, and trusts PID liveness without process-start identity. Electron-first or simultaneous startup can produce two primaries; stale marker PID reuse can incorrectly disable Electron persistence for the full run.

Required before PASS

  • Preserve scroll during cache eviction while still invalidating message-loaded authority.
  • Use runtime-binding compare-and-set settlement for restore completion and make ownership release lazy/request-scoped.
  • Retry deletion for previously cancelled creation requests when the prior deletion failed.
  • Give the server a graceful desktop shutdown control and full cleanup budget; never finish ordinary Electron shutdown while the tracked CLI remains unconfirmed alive.
  • Replace the one-way PID probe with a shared atomic cross-host lease used by both Electron and Tauri.

Validation observed

  • Electron native suite: 67 passed.
  • Focused restore suite: 54 passed.
  • UI, Electron and server typechecks: passed.
  • Server/UI/Electron builds: passed.
  • Known residuals: real Darwin runtime coverage is unavailable locally; two direct Node 25 UI suites still hit the existing solid-toast client-only loader issue.

@pascalandr

Copy link
Copy Markdown
Contributor Author

Gatekeeper review: BLOCK

This review supersedes the earlier gatekeeper report and evaluates the latest PR state at 08e175de. Scope: the complete origin/dev...HEAD diff, 114 files, 3 commits, 9,313 additions and 12,290 deletions. Three domain reviews and two independent adversarial checks were used; only confirmed findings are included below.

Blocking findings

  1. Critical: Windows session-end exits before process cleanup is guaranteed.

    • packages/electron-app/electron/main/client-state-lifecycle.ts:63-68,115-123,150-153
    • query-session-end is vetoed with preventDefault(), then shutdown is raced against a 1.5-second timeout that calls app.exit(0). The CLI process-tree deadline is 30 seconds. With active workspaces, Electron can exit roughly 28.5 seconds before forced tree enforcement, leaving Node/OpenCode descendants alive while also delaying the OS session-end request. The lifecycle test currently codifies exit while CLI stop is still hung.
  2. Critical: Electron force cleanup can kill an unrelated process after PID reuse.

    • packages/electron-app/electron/main/process-stop.ts:33-87
    • packages/electron-app/electron/main/process-manager.ts:314-329
    • POSIX traversal and Windows taskkill /PID /T /F retain only the original numeric PID. If the CLI exits and that PID is reused before the delayed exit callback/force deadline, CodeNomad can kill the unrelated replacement process and its descendants. The server workspace runtime has identity guards; Electron's final enforcement does not.
  3. High: any CLI exit is treated as successful cleanup even without the completion handshake.

    • packages/electron-app/electron/main/process-stop.ts:90-105
    • packages/electron-app/electron/main/process-manager.ts:343-361
    • The exit event resolves shutdown and cancels enforcement regardless of CODENOMAD_SHUTDOWN_STATUS:complete. If the CLI crashes after receiving the graceful command but before detached workspace cleanup completes, Electron only logs the missing handshake and exits, allowing detached workspace processes to survive.
  4. High: a successful force dispatch can leave ordinary Electron shutdown pending forever.

    • packages/electron-app/electron/main/process-stop.ts:108-123
    • When force() returns true, no confirmation poll or terminal deadline remains; the promise waits only for an exit event. A successful signal/taskkill dispatch is not proof that process exit was observed. Normal before-quit awaits this without an outer bound.
  5. High: simultaneous Electron/Tauri startup can permanently elect no primary.

    • packages/electron-app/electron/main/client-state-process.ts:477-499
    • packages/electron-app/electron/main/client-state.ts:140-173
    • packages/tauri-app/src-tauri/src/client_state/process.rs:61-70,110-129
    • packages/tauri-app/src-tauri/src/client_state/cross_host.rs:143-153
    • Both hosts publish legacy running markers before checking the opposite host. Under simultaneous startup, each sees the other's marker, both suppress candidacy, and neither creates primary.owner.json. Both remain secondary for their lifetime, so restore and persistence are disabled. Existing interoperability tests bypass this full legacy-marker phase.
  6. High: participant publication races primary release and breaks the cohort barrier.

    • packages/electron-app/electron/main/client-state-cross-host.ts:252-300,310-320
    • packages/tauri-app/src-tauri/src/client_state/cross_host.rs:178-257,291-312
    • A secondary can observe the owner and pause before publishing its participant. The primary then sees no other participant and removes the owner; the secondary publishes afterward, and a third client becomes primary without checking participants. This permits restoration while a client from the prior cohort remains alive.
  7. High: stale UI requests can resurrect deleted sessions and repopulate cleared message caches.

    • packages/ui/src/stores/session-api.ts:350-369,531-568,1039-1170
    • Search and parent-chain responses insert sessions without rechecking authoritative deletion. Message loading validates existence only before awaiting the request, then unconditionally restores messagesLoaded and seeds messages. A delete or cache eviction during the request is therefore reversed by the stale response, exposing zombie sessions or defeating the five-session cache bound.

Required implementation direction

  • Put the Electron CLI/workspaces under OS-owned containment where possible, especially a Windows Job Object with kill-on-close. Identity-guard every fallback signal and distinguish signal dispatch from confirmed process exit.
  • Make shutdown return an explicit complete/incomplete result. A CLI exit without complete must trigger identity-safe descendant enforcement; ordinary quit also needs a bounded terminal policy.
  • Replace separate cross-host owner/participant check-then-act operations with one serialized protocol shared by Node and Rust. Legacy markers should not make both new clients suppress candidacy.
  • Add a per-session lifecycle epoch/abort token and require it to remain current before committing sessions, messages, loaded flags, metadata, or search results. Centralize tombstone-aware insertion instead of mutating session maps in several async paths.

Validation status

  • Local focused suites passed before this review: Electron 83 passed / 1 platform skip, UI 67 passed, server 54 passed / 2 Darwin skips, Tauri 32 passed.
  • UI, Electron and server typechecks passed; cargo check and focused Rust formatting passed.
  • UI, Electron and server production builds passed.
  • Current GitHub builds are successful for Electron Windows/Linux/macOS and Tauri Linux/macOS ARM64; Tauri Windows and macOS are still running at publication time.

Passing tests/builds do not cover the interleavings above. The PR should not merge until these blockers are fixed and regression tests exercise the exact races.

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29451033896

Artifacts expire in 7 days.
Artifacts:

  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-tauri-macos
  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-tauri-windows
  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-electron-macos
  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-tauri-linux
  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-tauri-macos-arm64
  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-electron-linux
  • pr-602-08e175debb362afc30fd4d66f00505b2512a52f3-electron-windows

@pascalandr

Copy link
Copy Markdown
Contributor Author

Ponytail review: CHANGES REQUIRED

Reviewed the entire PR at dde26dce against origin/dev, not only the latest commit. Ponytail criteria: does the code need to exist, can an existing/native primitive replace it, and what is the smallest implementation that preserves correctness? Three focused reviews covered UI/server ownership, desktop process lifecycle, and Electron/Tauri election.

Merge blockers

  1. High: simultaneous upgraded Electron/Tauri startup can still elect no primary.

    • packages/electron-app/electron/main/client-state.ts:140-166
    • packages/electron-app/electron/main/client-state-process.ts:491-499
    • packages/tauri-app/src-tauri/src/client_state/process.rs:69-70,110-114
    • packages/tauri-app/src-tauri/src/client_state/cross_host.rs:151-159
    • Both hosts publish their legacy marker before checking the other host. If both markers become visible first, both suppress shared candidacy and remain secondary. The interoperability fixture disables Electron legacy detection with legacyTauriDataPath: null, so the green simultaneous test does not exercise the real full-host path.
  2. High: crashing during protocol-lock initialization wedges election permanently.

    • packages/electron-app/electron/main/client-state-cross-host.ts:210-238
    • packages/tauri-app/src-tauri/src/client_state/cross_host.rs:510-541
    • The fixed protocol.lock directory becomes visible before owner.json is complete. A crash between those operations leaves an ownerless/malformed lock that every later client treats as uncertain and never retires. Restore then remains disabled until manual filesystem cleanup.
  3. High: crashing after removal-claim publication also wedges stale recovery.

    • packages/electron-app/electron/main/client-state-cross-host.ts:264-289
    • packages/tauri-app/src-tauri/src/client_state/cross_host.rs:555-581
    • A claimant can publish removed.<digest>.claim and die before unlinking the stale owner. Every successor sees EEXIST and refuses recovery forever. The claim protocol prevents delayed unlink but introduces a permanent crash state.
  4. High: bounded cancellation history can invalidate a successful cancellation.

    • packages/server/src/workspaces/manager.ts:505-509
    • Evicting the oldest cancellation after 1,024 entries is not ownership-safe. A delayed creation whose record was evicted can resume and launch even though its cancellation previously succeeded. Keep each cancellation until its matching creation settles; do not use an arbitrary global count cap.
  5. High: pre-response restore cancellation still has a one-shot failure path.

    • packages/ui/src/stores/instances.ts:981-988
    • If the initial cancellation request fails before workspace correlation and the SSE event is absent/disconnected, no bounded retry occurs and the abandoned server launch can survive. Reuse the existing bounded cancellation helper for this path.
  6. High: Windows direct workspace descendants can escape after their leader exits.

    • packages/server/src/workspaces/runtime.ts:589-624,659-674,713-714
    • If opencode.exe starts a child and exits before cleanup, ancestry can no longer be reconstructed. The tracked leader is gone, guarded selection finds no owned process, and the workspace record is removed while the child survives. This needs a native ownership primitive or another mechanism that retains descendant ownership before leader exit, plus a real Windows regression test.
  7. Medium: legacy Tauri detection is PID-reuse unsafe.

    • packages/electron-app/electron/main/client-state-process.ts:94-110
    • A stale legacy marker whose PID is reused by an unrelated process disables Electron persistence for that process lifetime. PID-only liveness is not ownership evidence.

Smallest better implementation

The cross-host protocol is doing more work than necessary. Keep both existing host-local elections, but replace the new mutex/claim sequence with one complete temporary ownership directory atomically renamed to the fixed owner path. Publish participants atomically, never delete the owner during ordinary primary release, and retire a stale owner directory only after identity validation and confirming no live participants. The owner UUID itself can name participants/retirements.

This removes protocol.lock, owner-file initialization races, removal claims, release-time owner deletion, retry sleeps, SHA-256 naming, and the Rust sha2 dependency. Estimated reduction: 250-350 production lines and 100-150 test lines.

Optional deletions

  • Delete the unreachable Electron utility-supervisor path: shouldUsePackagedShellSupervisor() always returns false. Estimated reduction: 230-270 lines, including cli-supervisor.cjs and utility-only branches.
  • Inline the one-call session-cache-eviction.ts helper. Estimated reduction: 8-12 production lines plus helper-specific test plumbing.
  • Delete unused compatibility/test-only aliases in session-state.ts and attachments.ts. Estimated reduction: roughly 15-25 lines.
  • Do not add a generic lifecycle framework, database lease, daemon, heartbeat, TTL, background janitor, or file-length-only refactor. None is justified here.

Required focused tests

  • Real full Electron and Tauri startup simultaneously with legacy detection enabled.
  • Crash immediately after protocol ownership-directory creation/publication and during stale retirement.
  • Cancellation failure before correlation with no SSE replay.
  • More than 1,024 unresolved cancellation requests.
  • Real Windows leader exit with a surviving direct descendant.
  • Legacy marker with PID reused by an unrelated process.

Validation observed

  • Electron native: 86 passed.
  • UI focused authority tests: 8 passed.
  • Tauri client-state: 33 passed.
  • Focused server process tests: 28 passed, 2 Darwin skips.
  • UI/Electron/server typechecks and cargo check passed.

The green suites do not cover the crash/interleaving cases above. The PR should not merge yet.

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29454203385

Artifacts expire in 7 days.
Artifacts:

  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-tauri-macos
  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-electron-macos
  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-tauri-windows
  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-tauri-macos-arm64
  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-tauri-linux
  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-electron-linux
  • pr-602-dde26dce6c21623f30da13d707f7f2b0d1406a03-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29459180943

Artifacts expire in 7 days.
Artifacts:

  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-tauri-macos
  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-tauri-windows
  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-electron-macos
  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-tauri-linux
  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-tauri-macos-arm64
  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-electron-linux
  • pr-602-93fc2409399b0bad3b6be864d6ed16916d195e8a-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29483622027

Artifacts expire in 7 days.
Artifacts:

  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-tauri-macos
  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-tauri-windows
  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-electron-macos
  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-tauri-linux
  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-tauri-macos-arm64
  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-electron-linux
  • pr-602-7a5f6e62cf68923cbde15f266535ec4522277eef-electron-windows

@pascalandr

Copy link
Copy Markdown
Contributor Author

Gatekeeper review: CHANGES REQUIRED

Review of the full origin/dev...7a5f6e62 range. The platform builds are green, but the following correctness issues remain merge-blocking.

1. High: simultaneous stale-owner recovery can leave every host permanently secondary

Both hosts publish their participant before attempting stale-owner retirement. Retirement is then refused whenever another live participant exists. If Electron and Tauri start together after a primary crash, each sees the other participant, both refuse retirement, and neither retries or promotes later.

  • Electron: packages/electron-app/electron/main/client-state-cross-host.ts:159-174, :228-263
  • Tauri: packages/tauri-app/src-tauri/src/client_state/cross_host.rs:221-265, :282-306, :461-492

Impact: both clients skip restoration and reject all shared-state writes for their lifetime. Add a barrier-controlled stale-owner test where both hosts publish before retirement and assert exactly one primary.

2. High: an outgoing Tauri renderer can commit after authority rotates

The Tauri commands validate the renderer token before entering write_lock. Navigation can rotate renderer_access while an already-validated save, clear, or preference mutation is waiting or writing. The final atomic replacement only revalidates process ownership, not renderer authority.

  • Validation: packages/tauri-app/src-tauri/src/client_state/commands.rs:95-123
  • Mutation/write boundary: packages/tauri-app/src-tauri/src/client_state.rs:276-327, :345-370

Reproduction: claim token A, block an A save before replacement, claim token B during navigation, then release A. A can still replace or clear B's state. Fence mutations with an access generation revalidated under the write lock and immediately before replacement; add deterministic save/clear versus token-rotation tests.

3. High: a non-authoritative workspace stop can erase a restored tab and unsent draft

workspace.stopped removes the instance with authoritative: false, but still clears all drafts, attachments, session indexes, and the current tab. Snapshot reconciliation only reinserts absent pending results; a settled restored result is omitted.

  • Removal: packages/ui/src/stores/instances.ts:734-738, :849-913
  • Reconciliation: packages/ui/src/stores/app-session-snapshot-merge.ts:206-230

After a successful restore, type a draft, let it persist, then let the workspace process stop unexpectedly. The next capture overwrites the prior snapshot without that workspace or draft. Add coverage for a settled restored result followed by a non-authoritative stop.

4. High: delayed HTTP message hydration can roll back newer SSE state

Message-load epochs protect deletion, eviction, and competing HTTP loads, but SSE message/part updates do not advance the epoch. A delayed HTTP response therefore remains current and hydrateMessages() replaces messageIds plus matching records with its older snapshot.

  • HTTP commit: packages/ui/src/stores/session-api.ts:1063-1088, :1181-1188
  • Destructive hydration: packages/ui/src/stores/message-v2/instance-store.ts:434-510

Interleave a pending session.messages request with message.updated or message.part.updated; the newer message can disappear or streamed content can regress. Add an SSE-versus-HTTP authority/revision fence and regression test.

5. High: concurrent Electron restarts can spawn an untracked CLI server

cli:restart is not serialized. Two requests can both stop the old child, both pass start() while this.child is empty, await entry resolution, and spawn independently. The later assignment overwrites this.child, leaving the first detached server unmanaged. Restart racing application shutdown can similarly spawn after shutdown targeted the old child.

  • IPC: packages/electron-app/electron/main/ipc.ts:42-45
  • Start/stop lifecycle: packages/electron-app/electron/main/process-manager.ts:143-186, :237-292

Serialize/coalesce start, stop, and restart, and reject stale starts after shutdown begins. Add concurrent restart and restart-versus-quit tests.

6. High: Tauri Windows session-end can force-exit before native state is flushed

WM_ENDSESSION starts asynchronous cleanup and returns immediately. Cleanup waits for manager.stop() before client_state::flush_and_release(), while the session-end watchdog force-exits after 1.5 seconds.

  • Ordering and watchdog: packages/tauri-app/src-tauri/src/shutdown.rs:193-225
  • Windows callback: packages/tauri-app/src-tauri/src/shutdown.rs:273-303

A slow CLI stop can therefore guarantee that the internal forced exit occurs before the final native snapshot/window write. Flush and release client state before waiting for CLI shutdown, and cover a blocked CLI plus dirty state.

7. Medium: shared window bounds mix inner and outer dimensions

Tauri stores outer_position() with inner_size() and restores with set_size(). Electron stores getNormalBounds() and restores with setBounds(), both outer-window dimensions. Every Electron/Tauri handoff changes decorated window dimensions by the frame/title-bar size.

  • Tauri: packages/tauri-app/src-tauri/src/client_state/window.rs:147-165, :298-300
  • Electron: packages/electron-app/electron/main/window-state.ts:115-122, :219-230

Define one shared geometry contract and add a cross-host round-trip test, including non-1.0 DPI.

Coverage gate

The current PR checks package successfully, but do not execute the modified Electron native, UI Node, server lifecycle, or Rust regression suites. Add required CI jobs for these paths; compilation alone does not exercise the races above.

Verdict: request changes. The shared-state and lifecycle paths can still lose restore data, suppress persistence for an entire run, or leave an unmanaged server.

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29497579789

Artifacts expire in 7 days.
Artifacts:

  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-tauri-macos
  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-tauri-macos-arm64
  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-electron-macos
  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-tauri-windows
  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-tauri-linux
  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-electron-linux
  • pr-602-1057cb640892b728fb636add3196c5350a5b3ca1-electron-windows

@pascalandr

pascalandr commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Consolidated gatekeeper review: CHANGES REQUIRED

This review supersedes the measured and exhaustive reviews and removes their duplicates. Scope: full 40cee071a35ccbd2b61776e23f72a043a7eeaffc...1057cb640892b728fb636add3196c5350a5b3ca1.

Consensus findings independently confirmed by both reviews

  1. High: packages/ui/src/stores/client-state-codec.ts:25,38-42,165-170,196-205 normalizes the globally active tab before reserving inactive tab identities against the shared 96 KiB budget. Large active-tab payloads can therefore omit inactive activeParentSessionId/activeSessionId values or entire tabs, directly reproducing the reported Tauri restoration failure.
  2. Medium: packages/ui/src/stores/client-state-codec.ts:112-115,196-205 prioritizes selected drafts only for the globally active tab. An inactive tab with 24 older drafts can retain its selected session while losing that session draft. This behavior predates the PR but remains in the rewritten codec.

Additional High findings from the exhaustive review

  1. Non-authoritative workspace stops can replace complete preserved state with incomplete runtime capture.
  2. HTTP history rejected after an SSE race is not retried, leaving historical messages absent.
  3. Streamed deltas do not advance hydration authority and can be overwritten by stale HTTP content.
  4. Unknown message/part removals can be resurrected by pending hydration.
  5. Simultaneous stale-owner recovery can leave every Electron/Tauri claimant secondary.
  6. A surviving secondary never assumes persistence after the primary exits.
  7. Electron can commit an outgoing renderer mutation after authority rotation.
  8. Windows Electron process capture fails against the real CIM table and mismatches process identities.
  9. Electron starts server teardown before renderer snapshot capture completes.
  10. Released workspace creation requests can be reactivated and later delete a user-owned workspace.
  11. Signal-driven standalone server shutdown can remain alive indefinitely while stdin stays open.

Additional Medium findings

  1. Active-tab attachments can exhaust the global attachment budget before inactive selected attachments.
  2. Capped session refreshes discard workspace-routing hints needed by restored worktree sessions.
  3. Message-load epochs can collide after removal and reopening of identical IDs.
  4. Preserved drafts/attachments are not hydrated when missing sessions later become available.
  5. Cross-client explicit workspace deletion is treated as transient unavailability and can be undone on restart.
  6. Closing a restore-reused retained workspace can leave its runtime running.
  7. Stopped/error server records can be reconciled as usable workspaces.
  8. Electron Windows session-end handling does not guarantee persistence or recover from cancelled logoff.
  9. Failed Electron cleanup is permanently cached and cannot retry.
  10. Tauri Windows force-timeout can be prevented by its own exit handler.
  11. Electron overwrites normal bounds while maximized/fullscreen.
  12. Tauri mixes coordinate systems on mixed-DPI monitor layouts.
  13. Future-version legacy envelopes can be shadowed by writable v1 shared defaults.
  14. Retained legacy host files can resurrect cleared state.
  15. Electron process cleanup misses descendants created during graceful shutdown.
  16. Writer and decoder charge the 96 KiB budget asymmetrically.
  17. PR CI packages applications but executes none of the changed behavioral suites.

Validation

Electron native 92 passed; Tauri Rust 65 passed; focused server suites up to 64 passed; focused clean-head UI codec/merge 50 passed with 2 skipped; typechecks, cargo check --locked, production builds, and git diff --check passed. Deterministic reproductions confirmed the principal persistence, hydration, election, stale-renderer, request replay, and window-bounds findings.

Recursive review budget

1 root orchestrator, 10 direct leads, 90 descendants. The host plugin reached 100/100 and rejected further launches.

Final decision: CHANGES REQUIRED

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29514984984

Artifacts expire in 7 days.
Artifacts:

  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-tauri-macos
  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-electron-macos
  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-tauri-windows
  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-tauri-linux
  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-tauri-macos-arm64
  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-electron-linux
  • pr-602-13660a248032137ecd58c8d7c03b15591bd216eb-electron-windows

@pascalandr

Copy link
Copy Markdown
Contributor Author

Restore follow-up: contingency diagnostic ledger

This note preserves verified alternatives from the recursive investigation in case the Windows artifact at 73623b55 still fails. It is not a new gatekeeper verdict.

Reproduced primary failure

  • Before restart, the shared snapshot stored [DreamX-World, CodeNomad] with activeTabIndex: 1. After restart it was rewritten as [CodeNomad, DreamX-World] with activeTabIndex: 0.
  • DreamX retained saved session IDs and scroll snapshots on disk, but lost runtime Idle, selection, scroll restoration, and its restored order binding.
  • Cause: a transient initial session.list rejection aborted restoration for that workspace. The later connected-event resync repopulated sessions but did not replay saved state.
  • Fix 73623b55: settle the failed initial prerequisite and continue direct saved-ID hydration, preserving payload and original tab order.

Verified fallback risks

  1. Duplicate-folder occurrence drift: filtering non-ready workspaces before reconciliation can renumber same-folder occurrences and bind saved state to the wrong runtime. Not applicable here because DreamX and CodeNomad are unique folders.
  2. Pending duplicate capture: a user-created same-folder runtime can claim a pending saved duplicate. Not applicable to this unique-folder reproduction.
  3. Windows worktree hint mismatch: literal directory comparison can miss equivalent paths with different case, separators, or trailing slashes and route history incorrectly.
  4. Same-ID reuse: teardown can leave message loaded, loading, or error guards authoritative over a newly empty message store. Not the normal cold-start path.
  5. Active-only message hydration lacks a direct integration test for inactive restored tab -> activation -> correctly routed history request.
  6. Snapshot limits remain order-sensitive above 32 tabs or near the shared 96 KiB string budget. This two-tab snapshot ruled that out.
  7. Sustained SSE revision conflicts can repeatedly invalidate HTTP message seeding. This does not explain the reproduced loss of tab order and runtime metadata.

Missing regression coverage

  • Initial session.list rejects, saved IDs hydrate directly, and selection, Idle, scroll, and order still restore.
  • Inactive restored workspace activation performs one correctly routed history request.
  • Mixed-readiness duplicate folders preserve occurrence identity.
  • Equivalent Windows directory spellings produce the same workspace hint.
  • Same-ID instance reuse clears stale message-load guards.

Validation

  • UI typecheck passed.
  • UI production build passed.
  • 65 restoration, reconciliation, and codec tests passed.
  • 13 instance runtime authority tests reported passing; the browser-conditioned Node process retained open handles after completion.

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29531269244

Artifacts expire in 7 days.
Artifacts:

  • pr-602-73623b55600a60c3718cd6cd57fb35c37be41bce-electron-macos
  • pr-602-73623b55600a60c3718cd6cd57fb35c37be41bce-tauri-windows
  • pr-602-73623b55600a60c3718cd6cd57fb35c37be41bce-tauri-macos-arm64
  • pr-602-73623b55600a60c3718cd6cd57fb35c37be41bce-tauri-linux
  • pr-602-73623b55600a60c3718cd6cd57fb35c37be41bce-electron-linux
  • pr-602-73623b55600a60c3718cd6cd57fb35c37be41bce-electron-windows

@pascalandr

pascalandr commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Temporary test-only commit: 053d3f01 raises PROJECT_SESSION_LIST_LIMIT from 1,000 to 10,000 because the current large workspace needs it for artifact testing. Remove this commit from PR #602 before merge. The limit change will be submitted as a separate PR.

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29533701164

Artifacts expire in 7 days.
Artifacts:

  • pr-602-053d3f01d76c203cdea2a3e8afdc30adc0726f3b-electron-macos
  • pr-602-053d3f01d76c203cdea2a3e8afdc30adc0726f3b-tauri-linux
  • pr-602-053d3f01d76c203cdea2a3e8afdc30adc0726f3b-electron-linux
  • pr-602-053d3f01d76c203cdea2a3e8afdc30adc0726f3b-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29534477076

Artifacts expire in 7 days.
Artifacts:

  • pr-602-11e1ecbb7e694757f12ae57271239abcc42bdce0-tauri-windows
  • pr-602-11e1ecbb7e694757f12ae57271239abcc42bdce0-tauri-linux
  • pr-602-11e1ecbb7e694757f12ae57271239abcc42bdce0-electron-linux
  • pr-602-11e1ecbb7e694757f12ae57271239abcc42bdce0-tauri-macos-arm64
  • pr-602-11e1ecbb7e694757f12ae57271239abcc42bdce0-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29537850487

Artifacts expire in 7 days.
Artifacts:

  • pr-602-5b957cad2c8f1d4de8daf3805a5c3244e19c39fa-tauri-windows
  • pr-602-5b957cad2c8f1d4de8daf3805a5c3244e19c39fa-tauri-macos-arm64
  • pr-602-5b957cad2c8f1d4de8daf3805a5c3244e19c39fa-tauri-linux
  • pr-602-5b957cad2c8f1d4de8daf3805a5c3244e19c39fa-electron-macos
  • pr-602-5b957cad2c8f1d4de8daf3805a5c3244e19c39fa-electron-linux
  • pr-602-5b957cad2c8f1d4de8daf3805a5c3244e19c39fa-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29539162767

Artifacts expire in 7 days.
Artifacts:

  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-tauri-macos
  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-electron-macos
  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-tauri-windows
  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-tauri-linux
  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-electron-linux
  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-tauri-macos-arm64
  • pr-602-532aefa49eeedc71fe74bd6afce20a9db7bcfba4-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29540132194

Artifacts expire in 7 days.
Artifacts:

  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-tauri-macos
  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-tauri-windows
  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-tauri-macos-arm64
  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-electron-macos
  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-tauri-linux
  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-electron-linux
  • pr-602-71ebdd3274151aa8b184bb34aae125551483b6bf-electron-windows

Consolidate the desktop restore lifecycle and its regression coverage while preserving primary-process ownership, renderer authorization, active drafts, attachments, session tombstones, and cancellation semantics.

Bound workspace launches end to end, retain cleanup ownership after unexpected exits, and use identity- and token-guarded portable POSIX process-group cleanup. This avoids the macOS all-process ps timeout without introducing an unverified PID fallback, with real Darwin integration tests for CI.

Harden packaged Electron origins, transactional Tauri navigation authority, and bounded Windows session-end shutdown. Validation covers Electron, Tauri, UI, and server focused suites plus all TypeScript typechecks.
Restore workspace tabs without treating transient startup stops as user removals, hydrate saved session ancestry and metadata across worktree workspaces, and preserve scroll snapshots through cache eviction and late native seeding.

Keep Electron zoom consistent for native menu, keyboard, and wheel input across navigation and restart. Bound desktop shutdown, start CLI termination alongside state flushing, and use verified Windows process-tree escalation to avoid minute-long exits.

Treat Electron as a secondary client when a live Tauri marker already owns restoration, while retaining an independent CLI and manual workspace creation. Cancellation ownership is request-scoped so reused workspace launches cannot remove or retain the wrong instance.

Validated with UI and Electron typechecks, server typecheck, 67 Electron native tests, 54 focused restore tests, independent targeted reviews, and successful server/UI/Electron builds.
Prevent late restore completion and cleanup races from resurrecting explicitly closed workspaces. Preserve message scroll while invalidating evicted session hydration, retain scoped request correlation for shared launches, and retry failed cancellation cleanup safely.

Add confirmed graceful desktop shutdown with concurrent workspace cleanup and final process-tree enforcement. Introduce a shared Electron/Tauri cross-host election with atomic publication, identity-guarded stale recovery, cohort participants, legacy marker checks, and Node/Rust interoperability coverage.

Validated with focused UI, server, Electron, and Tauri suites; UI/Electron/server typechecks; cargo check and focused rustfmt; and UI, Electron, and server production builds.
Guard asynchronous session search, parent hydration, and message loading with deletion authority and per-session request epochs so stale responses cannot resurrect deleted or evicted state.

Make Electron shutdown identity-safe and bounded: do not veto or force-exit Windows session end, require the graceful completion handshake, capture immutable descendant identities, reject PID reuse, and confirm process disappearance after enforcement.

Serialize Electron/Tauri cross-host owner and participant transitions with a shared atomic lock so simultaneous startup elects one primary and participant publication cannot cross cohort release.

Validated with Electron native tests, focused UI and server suites, Tauri client-state tests, UI/Electron/server typechecks, cargo check, and focused Rust formatting.
Replace the cross-host mutex and claim protocol with atomically published owner directories and participants. This removes crash-wedged intermediate states, preserves live cohorts, handles upgraded and legacy markers, and drops the sha2 dependency.

Keep workspace cancellations until their matching creation settles and retry pre-response restore cancellation without relying on SSE delivery. Inline one-use cache eviction logic and remove unused aliases.

Delete the unreachable Electron utility-process supervisor path. The existing identity-guarded shutdown remains; Windows crash-only descendant containment is intentionally left as a documented residual rather than adding a PowerShell Job Object supervisor.

Validated with Electron native tests and build, focused UI/server suites, Tauri client-state tests, all affected typechecks, cargo check, and focused Rust formatting.
Persist Electron and Tauri restore data in one cross-host envelope, migrate legacy host files deterministically, and prevent cleared state from being resurrected. Keep atomic replacements on the destination filesystem and normalize Tauri window bounds for HiDPI handoffs.

Delay capture until native flush listeners are ready, preserve the saved active tab and session IDs during startup, accept legacy unversioned snapshots, and hydrate incomplete session metadata without overwriting newer updates.

Validated with 89 Electron native tests, 69 focused UI tests, 36 Tauri client-state tests, UI/Electron typechecks, cargo check, rustfmt, and the Electron production build.
Recover stale cross-host ownership deterministically when Electron and Tauri start together, and fence Tauri renderer mutations against authority rotation through the final atomic replacement.

Preserve restored tabs and unsent drafts after non-authoritative workspace stops, reject stale HTTP message hydration after newer SSE updates, and serialize Electron CLI lifecycle operations so restart cannot race shutdown or spawn an untracked server.

Flush Tauri client state before stopping the CLI, align shared window geometry on outer position plus content size, and discard incompatible legacy native bounds during migration.

Validated with 92 Electron native tests, 71 focused UI tests, 38 Tauri client-state tests, 7 Tauri shutdown tests, all affected typechecks, cargo check, focused rustfmt, and the Electron production build.
Preserve inactive workspace identities, selected drafts, attachments, and late prompt hydration so Electron and Tauri restore every tab instead of only the globally active one.

Fence renderer and message hydration races, harden cross-host stale-owner recovery, serialize shutdown after state capture, and make Windows process cleanup use consistent identities and refreshed descendant trees. Distinguish explicit workspace deletion from transient stops, prevent request ownership reactivation, and retire migrated legacy state without shadowing future envelopes.

Add PR behavioral checks and regression coverage across UI persistence, Electron lifecycle/process cleanup, server workspace shutdown, and Tauri client state. Validated with 93 Electron tests, 53 focused UI tests, 23 server tests, 65 Rust tests, all TypeScript typechecks, cargo check, targeted rustfmt, and the production UI build.
Continue restoring saved workspace state when the initial session-list request fails transiently. The direct saved-session hydration path can recover after reconnect, preserving selection, runtime markers, scroll position, and the original tab order instead of appending the unresolved workspace after the active tab.

This behavior is shared by Electron and Tauri. Validated with the UI typecheck, production build, 65 restoration and reconciliation tests, and 13 instance runtime authority tests.
Start applying the loaded snapshot immediately, matching the Tauri behavior before desktop state was shared with Electron. Flush listeners are still registered eagerly, but their asynchronous setup no longer delays tab ordering and session hydration behind workspace startup.

The focused source regression check now verifies both listeners remain registered without blocking restoration. UI typecheck and the targeted test pass.
Restore-created workspaces previously mounted in parallel. Solid could invoke Virtua refs before document adoption, causing ResizeObserver initialization to throw after the workspace entered the UI but before its restore binding committed. The affected tabs then lost saved ordering, session selection, idle markers, scroll snapshots, and generation recovery.

Create missing workspaces sequentially while preserving parallel hydration for existing workspaces and SideCars. Budget the startup deadline per serialized workspace and bound failed-creation cleanup so one stalled cancellation cannot block later tabs.

Validated with a packaged Tauri release against a three-workspace snapshot, confirming exact tab order, active tab, per-workspace active sessions, idle markers, scroll snapshot counts, and generation recovery. Added focused regression coverage and ran UI typecheck and restore tests.
New Electron, Tauri, and UI client state now starts with restoration disabled while preserving an explicitly persisted enabled preference. Parsing malformed or incomplete envelopes follows the same safe default across desktop hosts.

Tests that exercise persistence explicitly enable restoration, and the rebased interruption registry uses its public session-id view instead of stale internal maps.

Validation: UI and Electron typecheck passed; focused Rust tests reached 36/38 before the final fixture-only correction.
@pascalandr
pascalandr force-pushed the fix/restore-followup-578 branch from 71ebdd3 to f0a9fc3 Compare July 17, 2026 10:21
Move the server cancellation retry into a UI-independent module so the regression test can run under Node without loading Solid client-only notification code.

The instance store keeps correlation cleanup while delegating the retry itself to the tested helper.

Validation: typecheck passed; expanded UI restoration suite passed 84 tests with one pre-existing skip.
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29573189195

Artifacts expire in 7 days.
Artifacts:

  • pr-602-f0a9fc321581bb83d591126641c7d349f65d6e69-tauri-windows
  • pr-602-f0a9fc321581bb83d591126641c7d349f65d6e69-tauri-linux
  • pr-602-f0a9fc321581bb83d591126641c7d349f65d6e69-electron-macos
  • pr-602-f0a9fc321581bb83d591126641c7d349f65d6e69-electron-linux
  • pr-602-f0a9fc321581bb83d591126641c7d349f65d6e69-tauri-macos-arm64
  • pr-602-f0a9fc321581bb83d591126641c7d349f65d6e69-electron-windows

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29574059387

Artifacts expire in 7 days.
Artifacts:

  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-tauri-macos
  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-tauri-windows
  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-tauri-macos-arm64
  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-tauri-linux
  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-electron-macos
  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-electron-linux
  • pr-602-61ed1b16722fbd54e74335b4eecc45bcdbcdef0b-electron-windows

Do not mount the project-opening home while a saved session with tabs is still restoring. This removes the timing-dependent home flash whenever the runtime tab list is temporarily empty.

Persist an explicit homeActive marker so closing from the project home remains restorable without treating transient empty-tab gaps as user intent.

Validation: desktop typecheck passed; expanded UI restoration suite passed 86 tests with one pre-existing skip.
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29578576318

Artifacts expire in 7 days.
Artifacts:

  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-electron-macos
  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-tauri-windows
  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-tauri-macos
  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-tauri-macos-arm64
  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-tauri-linux
  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-electron-linux
  • pr-602-f3a9cc08768e42efd4694706d88898dc1b565a31-electron-windows

@pascalandr pascalandr left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gatekeeper review

  1. P1, blocking - packages/ui/src/App.tsx:633-643, packages/ui/src/lib/hooks/use-app-session-restore.ts:232

    Restoring homeActive=true while appTabs() is still empty mounts two FolderSelectionView instances: the empty-app home and the full-screen home overlay. Both register global keyboard/drop handlers, so one drop can trigger duplicate workspace creation. Only one home instance should mount while the tab list is empty.

  2. P3 - .github/workflows/pr-build.yml:88-93

    app-session-restore-gate.test.ts is not included in the workflow explicit UI test list, so this regression check does not run in PR CI.

The optional homeActive codec change is backward-compatible. Focused restoration tests and desktop typecheck pass.

Keep the empty-state home and the tab overlay mutually exclusive while restoring an explicitly saved home view. This prevents duplicate global keyboard and drop handlers from issuing repeated workspace actions.

Run the restore-gate regression test in PR CI so the startup rendering contract remains covered.

Validation: desktop typecheck passed; focused restoration suite passed 56 tests.
@pascalandr

Copy link
Copy Markdown
Contributor Author

Gatekeeper follow-up: blocking duplicate-home finding fixed in d57449b. Empty-state home and tab overlay are now mutually exclusive, and the restore-gate regression test is included in PR CI. Validation: desktop typecheck and 56 focused restoration tests pass.

@pascalandr

Copy link
Copy Markdown
Contributor Author

@shantur LGTM

@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29580381412

Artifacts expire in 7 days.
Artifacts:

  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-tauri-macos
  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-tauri-windows
  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-electron-macos
  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-tauri-linux
  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-tauri-macos-arm64
  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-electron-linux
  • pr-602-d57449b01d4157b9b216d2b836fa674345184708-electron-windows

Create missing workspaces concurrently while serializing UI commits so restored tabs keep their saved order without paying the network latency sequentially.

Fence stale workspace-list and lifecycle events, preserve complete reopen state, and harden Electron, Tauri, and server process containment so cancellation and shutdown cannot leak or revive workspaces.

Require the expanded UI, server, Electron, Linux Rust, and Windows Rust checks before artifact publication. Validated with TypeScript typecheck, focused restore and shutdown suites, 99 Electron tests, and 76 Rust tests.
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29591185038

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@pascalandr pascalandr assigned pascalandr and shantur and unassigned pascalandr Jul 17, 2026
Keep ordinary workspace creation outside restore cancellation ownership and retire graceful cross-host ownership cohorts atomically so surviving secondary hosts cannot block later persistence failover.

Make shutdown status terminal, preserve the Tauri Windows graceful control channel, and move Electron tree enforcement off the main thread with handle-bound Windows identity checks and hard end-to-end deadlines. Windows session end now fails open only after a bounded primary release attempt.

Prepare clean Tauri test resources on Linux and Windows, run Windows PATH behavior on Windows, and make the Linux runtime harness observe exited processes. Regression coverage exercises ownership, repeated handoffs, PID reuse, malformed snapshots, hung enforcement, and session-end deadlines.
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29599169737

Artifacts expire in 7 days.
Artifacts: (none found on this run)

Pin the simulated runtime platform and return valid unrelated process snapshots after the owned child exits so Linux can prove cleanup instead of waiting on an invalid empty probe.

Align PID-reuse expectations with identity-safe cleanup and use a host-valid folder for simulated Windows launches. Verified with the runtime suite under both Linux Node in WSL and native Windows.
@pascalandr

Copy link
Copy Markdown
Contributor Author

@shantur LGTM

Normalize the native GetProcessTimes value to the microsecond precision exposed by CIM before comparing it with the captured creation identity. This keeps handle-bound PID reuse protection strict while allowing owned CLI processes to be terminated.

Add real Windows child-process coverage proving valid CIM identities terminate and sub-microsecond mismatches remain protected. Electron typecheck and all 117 native tests pass.
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29603542842

Artifacts expire in 7 days.
Artifacts:

  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-tauri-macos
  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-tauri-windows
  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-electron-macos
  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-tauri-linux
  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-tauri-macos-arm64
  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-electron-linux
  • pr-602-70493946e9fc1bb079cf2d4c742dcd22b19d3310-electron-windows

Enable restore for new or missing desktop preferences in both Electron and Tauri while preserving an explicitly disabled setting and keeping unsupported future state envelopes protected.

Clarify the localized startup setting so users know that unsent messages, window position, and zoom are restored. Add focused coverage for the new default and explicit opt-out behavior.

Validation: rustfmt --check passed for the touched Rust files; git diff --check passed. Full test execution was skipped at user request.
@github-actions

Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/29608098000

Artifacts expire in 7 days.
Artifacts:

  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-tauri-macos
  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-tauri-windows
  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-tauri-macos-arm64
  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-electron-macos
  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-tauri-linux
  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-electron-linux
  • pr-602-be1c053b4b9f90a0e039ee562b0bced87db3fe2d-electron-windows

@shantur
shantur merged commit 0bab9e3 into NeuralNomadsAI:dev Jul 17, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants