(session-state): one owner per remote row — local-pty while attached, the adapter otherwise - #275
Merged
Merged
Conversation
… the adapter otherwise Closes #273. Measured on v0.0.76: 53 response-ready flickers in 2 min on an attached remote session, and a 20 s busy tail after the process died. The remote adapter's watch, seed and decay writers now no-op while the row is attached, and the adapter's projection does not repaint an attached row; on detach the adapter takes over from the current state, cancels the decay, clears busy at once and floors the seed window so a stale remoteActiveAt cannot re-arm it. clearUnread carries its via.
This was referenced Sep 12, 2026
Merged
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.
Closes #273. Measured on v0.0.76 with the activity trace (local note
.work-files/switchboard/trace-2026-09-12.md): 53 painted response-ready flickers in 2 min 23 s on an attached remote session, and a 19.96 s / 20.05 s busy tail after the remote process died. Both reproduced on current main by replay tests before the fix (RED quoted in the test file names' first run).Root cause
Two writers on one row with no arbitration on the
attachedfact #267 already carried:markRemoteBusy/decayRemoteBusywrote the shared Maps throughsetActivitywhether or not the row was attached, andprojectRemoteStaterepainted the row from the adapter's private snapshot on every render;setRemoteAttachedonly toggled a field, so afterpty.exitbusy could only clear through the 20 s decay.Fix
session-state.md): attached remote row → local-pty path (OSC busy/idle, response-ready allowed); unattached → the remote adapter (watch, decay, never response-ready). Watch/seed/decay are no-ops while attached; the adapter's projection does not repaint an attached row.remoteSeedFloors) so a staleremoteActiveAtcannot re-arm busy.clearUnread(sessionId, via);clearNotificationspasses its via (thevia: undefinedseen in the trace).Proof
test/remote-row-ownership.test.js: symptom 1 (watch must not delete response-ready while attached) and symptom 2 (busy clears at the handoff instant) — both RED before, GREEN after.attachedguards → symptom 1 red; disabling the handoff block → symptom 2 red. Reverted.task check: 1277 + 119 pass, 0 fail, pre-existing skips.Known side effect, stated in the doc: while a remote row is attached,
agentsBusy/is-alivefrom the adapter are not repainted until detach (the local-pty path owns the row). Not verified live yet — next debug session.