Repository navigation
Two-computer relay: fast take-back, moved task pages, honest saving, and six rough edges - #1990
Merged
Merged
Conversation
Fetch the incoming objects, inspect only the workspace metadata in a scratch timeline, and leave an ordinary chat's one whole-tree restore until after its lease is acquired. Chats that carry a workspace plan, or an older root set, still run their full admission before the lease, and a refusal leaves the folder and the lease untouched. The holder also reads a retirement request without waiting for its presence heartbeat, so a displaced session lets go at once. Continuation phases can now be observed, and the first acquire after a killed holder lands well inside two seconds on a loopback relay. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When a chat arrives without its plan database, its finished tasks fill their rows and pages from the settled run receipt, the transferred trajectory and the local worker history. The page offers no task verbs, says the task has finished when asked to act, and never restarts a settled run. The sending computer's page is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The sealing notice says saving works again only after this chat's own transcript is sealed and, for a chat that syncs, published. A store whose lock is held but whose socket is gone is diagnosed in bounded time with a plain sentence, never retried into another writer, and restarted only when the process is proven to be this client's own storage child for that exact socket. Close errors now name where the unsaved turns are kept. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When the relay cannot be reached, cluster status and the leadership commands now use the same plain network sentence as devices, with no Go error text, and still exit non-zero. The sentence is shared rather than copied, and a removed device's own sentence still takes precedence. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ever freezes - Keys and pastes typed while /new opens belong to the new chat; Esc gives them back to the chat you were in, unsent, and says so. - A moved copy keeps its project label after this computer is removed. - Home never offers to continue this computer's own chat. - The first Enter in a copy held elsewhere asks a fresh, bounded ownership read instead of trusting a hint, so a reachable relay no longer reads as "other machines unreachable". - Closing a chat and quitting run the engine work off the update loop with a bound, and keys pressed meanwhile cannot send another chat's draft. - A final save that fails is said once on the terminal after the screen is restored, in one plain sentence. - The surface carries a once-per-outage "not syncing" notice behind an optional renewal-status interface. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n socket) furrow 0.3.5 records its socket's device and inode at bind time and removes the path at shutdown only while it still names that socket, so a daemon that outlived its client can no longer unlink the socket of the one that replaced it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ure reaches the terminal - The batcher keeps the first unreachable renewal or publish for the same hold and clears it on success; a displaced or removed hold reports none. That reading rides the engine host's facts as an optional field, so the surface's once-per-outage "not syncing" notice has a real source and an older peer simply reads as unknown. - Saving replies carry an optional transcript location. The host joins the agent's close with its final publication before it replies, and a detach is acknowledged only after the release, so a quit no longer exits while the engine is still saving and publishing. - The screen restores after its bounded wait while the launcher keeps the links open for the saving reply, then prints one plain sentence naming the transcript. A second ctrl+c exits at once even when cleanup is stuck. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…one clears The sealing watch now tracks this conversation's own turn boundary, so a later bookkeeping append cannot hide a turn that was saved, and a turn that has just started cannot borrow the previous one's saved head. Publication is required only where the drive will actually publish, so an unused startup chat that recovers locally clears. An idle hosted chat's notice crosses the host's notice frames, so "sealing works again" reaches the window even when no turn is running. A clean release also removes the matching local send hold. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ps every word - A chat this computer holds, or one never shared, sends from its local hold and fence with no relay request; a copy held elsewhere makes one bounded read, and an established outage is not paid for again on every send. - A reply that arrives after the draft or chat changed says why the words are still unsent instead of dropping them silently. - Any quit, including the terminal closing, folds the words typed while /new opens into the saved draft first. - A close that finishes late reports its failure in the chat now open, naming the chat it closed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
After the screen is restored the launcher waits for the final publish and release, says "saving this chat before quitting…" when that takes more than a moment, and stops at the existing save ceiling with the plain sentence. A real quit through the engine host is proven to release the chat, so the other computer's bare launch moves it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A deadline now says the sync service did not answer in time; only a refused connection, a missing route or a DNS failure says it cannot be reached. A joined computer's status reads the relay's answer without reopening the local member store, and the whole command is bounded by one ceiling. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The roster fixture now expects the read-only historical page a completed transferred task carries, keeping its recorded-model and journal checks. The services page names services in its title so a search for the word reaches it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e from defers The cluster command's formatting lives in clusterCommand again, with the bounded runner split out and its goroutine guarded, so a panic there cannot take the terminal down. The final-save and live-drive critical sections each move into a helper that unlocks from a defer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… chat back - The send shortcut that skips the relay now needs the agent's live held flag, not just a hold file on disk. A window another computer took asks before sending again, and a hold left by a process that died can never grant a send. - A writer that became a viewer cannot record a new hold, and an explicitly displaced writer with no rows keeps its words unsent. - On start and at a take, the saved hold is reconciled with the relay's record and retired when its device, fence or expiry is stale, so a computer that was killed and taken over takes the chat back on the first try from Home or from its own copy's card. - The card names the relay's real holder and last saved turn, and every take that falls to the catch-all sentence logs its real cause. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The directory client keeps the typed cause of an HTTP failure, so a deadline is no longer called a network fault, and the terminal and in-chat pairing doors say the shared did-not-answer-in-time sentence instead of raw Go error text. Cancelled is reserved for a person actually cancelling. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the relay is down With the relay unreachable or slow, the command printed the unavailable sentence and then a false "nothing is paired yet", and exited 0. It now prints only the plain unreachable or deadline sentence and exits non-zero, as cluster status does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The run history resolves a moved finished worker's transcript from the task store when the plan identity never arrived, so the page can show it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…wn chats - A card take consumes the words it sends: they are gone from every draft store once sent, a later take or restart opens an empty box, and the take opens exactly one conversation with no stray copy of the words. - A failed take, a cancelled card or a cancelled folder picker keeps the words once, in the box they were typed in. - The card never names this computer as the holder of its own chat, a landing never says it moved from this computer, and a kept branch counts the conversation turns that were actually unpublished. - A removed computer sends in a chat that was never shared and in the chat it held at removal, with no relay request; it refuses only a chat another computer took, with the removal sentence. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The pre-acquire inspection named its private timeline after the chat alone, so once a copy was filed into its project bucket the next take's staging folder no longer matched the binding the detached inspection timeline kept, and furrow refused every later take with "timeline is attached to another folder". The inspection timeline is now named from its scratch folder, so a chat can ping-pong between computers any number of times, and a home already holding the old binding takes the chat without any repair step. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The historical row now carries the receipt's conversation and run, so the Tasks door opens the read-only historical page whichever of the index and the roster arrives first, instead of keeping the summary card. The page also opens the work fold, so the worker's own reply and the recorded steps are on screen. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A window that has drawn "… continued this chat" could still send for a few seconds, because its drive kept believing it held the chat until its own next heartbeat failed; the turn ran, the publish was refused and the chat forked. Now the surface latches a send block as soon as a newer listing row or the displaced notice arrives, so the next Enter raises the continue card, and the drive follows the directory feed and retires its hold the moment another computer acquires the chat. A held chat with no displacement news still sends at once with no relay request. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The task history reader refused a symlink anywhere above the conversation, so on a computer whose home sits below an aliased folder (macOS's /tmp is /private/tmp) a moved task's worker transcript and steps could never be read, and its page showed only the summary. The trusted conversation location is now resolved first, while the task's own state, history, worker and trajectory files still refuse any redirect. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the window
- Draft storage is keyed per chat, so two copied chats from different
projects on one computer never share a draft, and a chat keeps its draft
through a move into its copy folder.
- A continue card shows only the words of the window that raised it and that
chat's own project; a card opened from a Home row shows that chat's draft or
nothing.
- Esc ("leave it there") on a card raised from a chat window goes back to that
window with the words still in its box.
- cluster status reads under one five-second ceiling, and Home says other
machines did not answer in time on a deadline instead of calling them
unreachable.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ks again A read that only hit its deadline no longer reads as other machines being unreachable: the window says they did not answer in time, keeps the words, and the next Enter makes a fresh read instead of replaying the cached failure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-only send block The displaced-window block set from a listing row or the displaced notice now yields to the reading a send makes itself: when that newer reading shows this computer holds the chat, the send goes ahead. A block a take decided, or a failed take, still never lifts that way. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Fixes everything the real two-computer relay tests found after #1944 (a PC under WSL and a Mac on a LAN relay, with real models), plus what three more real rounds on this branch found along the way.
Closes #1982, closes #1984, closes #1985, closes #1986.
What changes for a person
Moving a chat between computers
/quitwaits for the final publish and release before the process exits, so the other computer's bare launch lands on the chat. A long wait sayssaving this chat before quitting….Words and drafts
/newopens stay with the new chat, and survive the terminal closing.Saving tells the truth
sealing works againappears only once this chat's own turns are sealed and published again, and it reaches an idle chat.Tasks
/tmp.Rough edges (#1986), plus plain sentences
did not answer in time.codeaf cluster status,devicesand pairing say plain sentences when the relay is down or slow, and exit non-zero.Proof
devicesoffline;Left as follow-ups:
🤖 Generated with Claude Code