Skip to content

Journal Workspace transfers first; keep standalone state private and updates approved - #894

Merged
nedtwigg merged 16 commits into
spec-cleanup-cli-toolsfrom
spec-cleanup-standalone
Oct 2, 2026
Merged

nedtwigg merged 16 commits into
spec-cleanup-cli-toolsfrom
spec-cleanup-standalone

Conversation

@nedtwigg

@nedtwigg nedtwigg commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Audit the standalone and updater specs against both sides of the bridge. Journal Workspace transfers before changing ownership, fence late snapshot and geometry writes after a Window closes, and fall back to memory when private Burrow/recovery storage cannot be prepared. Preserve an approved updater download when a delayed launch check completes.

The specs retain the shipped transfer and close behavior and point to the native implementation. Validation: current macOS/Windows platform checks, standalone smoke test, and bot review pass; updater regressions cover the delayed check. Stacked on #893.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 17718de
Status: ✅  Deploy successful!
Preview URL: https://72ad06b2.mouseterm.pages.dev
Branch Preview URL: https://spec-cleanup-standalone.mouseterm.pages.dev

View logs

@dormouse-bot dormouse-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A return whose reverse journal keeps failing now blocks quit with no bound. hand_back_arrival leaves the arrival Returning in the queue, and retry_arrival_return re-runs it every second until the write succeeds. While any record is queued, defer_quit (quit_state.rs) returns Some, and request_quit returns early with "transfer in progress; quit queued until settlement". It doesn't spawn its watchdog in that case. So if the sessions directory becomes permanently unwritable (disk full, read-only volume, revoked permission) while a Workspace is being handed back, every Quit trigger is swallowed and only a force-kill ends the app. Before this PR the record left the queue whatever the write result.

Blocking quit here doesn't seem to protect anything. A failed reverse write leaves the initial journal record in place, unchanged per commit_arrival_return_with. restore_arrivals already recovers that record into the target on the next launch. Bounding the retry chain, or letting a deferred quit proceed past a Returning arrival whose write keeps failing, would keep recovery without trapping the user. This is a design call for whoever owns the "retain a failed return as an in-flight blocker" rule in standalone.md.

Comment thread standalone/src-tauri/src/lib.rs Outdated
Comment thread standalone/src-tauri/src/lib.rs
@nedtwigg
nedtwigg added this pull request to stack #896 October 2, 2026 05:05
nedtwigg and others added 7 commits October 1, 2026 22:43
The original change answered two local disk-write failures with about
1,000 lines of new state: four arrival phases, commit_*_with helpers,
5x1s return retries, RecoveryPending parking, CloseCommit with snapshot
rollback, retainWindowAfterFailure/retryLatest, and new teardown-modal
states. Both failures need the app-data write itself to fail (disk full,
antivirus holding the rename), and the transfer case also needs a crash
inside a sub-second window. Meanwhile the machinery added ways to get
stuck: an undismissable close-commit-uncertain modal with saves refused,
RecoveryPending blocking closes and transfers at both windows until
restart, a drag that now failed when the settled-journal write did, and
(until review caught it) a quit that could hang forever. Close retention
also kept a window open behind a Retry modal after the user asked to
close it, where the old outcome was only that window reopening on the
next launch with nothing lost.

Return to the base behaviour; the following commits keep the small,
independent fixes and replace the transfer guard with journal-first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…be locked

On Windows the Node stores' file modes are no-ops, so a refused DACL on the
state directory used to leave burrowToken written under the inherited ACL
with only a warning. prepare_owner_only_dir now publishes a directory only
after restrict_to_owner succeeds; otherwise the sidecar gets no directory
and keeps that state in memory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
runUpdateCheck awaited the 5 s delay and the network-policy read, then
called check() regardless, so an update approved through Check now in that
window was offered for approval a second time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node's --import needs a file URL on Windows, and kill('SIGTERM') there
terminates the child without running its JS handler, so the agent-browser
harness test delivers the signal over IPC on win32. standalone.md named the
retired AGENT_BROWSER_TIMEOUT (30s); the constant is BROWSER_REQUEST_TIMEOUT
(40s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Destroyed used to drop the save refusal, but a save_session dispatched
before Destroyed can take the disk lock after it and recreate the removed
snapshot. Labels are never reused within a process, so the refusal now
lasts until exit. The debounced geometry flush now rechecks that refusal
under the same disk lock close removal holds, so a flush captured before
the close cannot write the geometry file back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
begin_arrival moved the shells to the target and only then wrote
sessions/arrivals.json, logging a failed write and carrying on, so a crash
after that failure restored the in-flight Workspace in neither window.
journal_and_open_arrival now writes the record first and refuses the move
with nothing changed if the write fails. The write runs outside the
arrivals lock, whose waits reach the main thread, so admission is checked
again under that lock and a refusal there withdraws the record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nedtwigg nedtwigg changed the title Preserve standalone state through transfer and close failures; audit host specs Journal Workspace transfers first; keep standalone state private and updates approved Oct 2, 2026
@nedtwigg
nedtwigg merged commit 5ce9132 into main Oct 2, 2026
10 of 12 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