Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't workingneeds-triageremoteRemote workrooms: hosts, providers, the far-side agent and brokerRemote workrooms: hosts, providers, the far-side agent and broker
Description
🤖 Left by Claude Code. This is the status of every follow-up from the #356 reviews and PR #372, as of its merge (2026-10-07). Details for each item are in the comments below. Before working on any of them, check it against actual and plausible use, per AGENTS.md "Reviews & Reported Bugs". Most are unlikely.
Fixed in PR #372
- 1. An unanswered presence read is now cached for
retryAfter. - 2. A cancelled snapshot removal in
destroyis rethrown, not swallowed. - 4. The "left live" log names the destroyed workroom when nothing is live.
- 5. A take-back across the let-go's disconnect keeps the connection (
HostConnectionManager.disconnect(_:unless:)). - 6 (part). A late idle-window read no longer brings back a deleted host's model.
Fixed in PR #375
- 16. A remote create no longer needs
gh: whengh repo viewcan't name the repository, it readsoriginwith git.
Fixed in PR #381
- 6 (rest).
connect'smodel(forHost:)can still make a model if a delete lands mid-connect, andRemoteHostsnever prunes its per-host dictionaries. Rare; the cost is a small leak. - 8. Decide: should an old agent (no wakefulness service) hold its box for one ceiling after connect?
- 9. Concurrent presence reads aren't shared. Item 1's cache limits this to one burst per window.
- 13. Investigate: does the app make long or mutating calls on boxd hosts that aren't selected? If so, a let-go can cut one in flight.
- 17. A stale IDLE report can let a busy box go. Very unlikely; the cost is a missed prompt until the next revisit.
- 18. A connected box never sleeps while the app is open (a regression since the 2026-10-06 live pass, measured live; likely, and costly). Re-scoped by the owner: the box decides its own wakefulness, the app's let-go, poll, ceiling prompt and idle-window warnings go. The box decides its own wakefulness: agent-side let-go, pushed verdicts, no app-side wakefulness management #380. Items 6 (rest), 8, 9, 13 and 17 are edge cases of that removed logic and close with it.
Open
- 3. Restored-selection
selectinAppStorereload is untested; selection itself is tested. Low value. - 7. Investigate: can a create be cancelled, leaving a paid machine unrecorded?
- 10. Product question: show the last-known dirty state while a box sleeps or is let go?
- 11. Record a real
machine get --jsonwith both timers set, to confirm the idle-timer string format. - 12. Stale doc comments: the
WakefulnessModelclass doc, theensureConnectedcallers, andminimumIdleWindowvs the RustINTERVAL_S. - 14. Have
deletionKeyrefuse a boxd record with noaccount(corrupt config only). - 15. Create-progress steps can apply out of order. Cosmetic.
Item 16 moved to fixed by Claude Code at the owner's request, 2026-10-08 (PR #375).
Item 18 added by Claude Code at the owner's request, 2026-10-08 (#380).
Items 6 (rest), 8, 9, 13, 17 and 18 moved to fixed by Claude Code at the owner's request, 2026-10-09 (PR #381).
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingneeds-triageremoteRemote workrooms: hosts, providers, the far-side agent and brokerRemote workrooms: hosts, providers, the far-side agent and broker
Activity
joelmoss commentedon Oct 7, 2026
5. Let-go commit and disconnect race
RemoteWorkrooms.swift,RemoteHosts.observed: the last locked check runs, and then the code awaits an actor hop beforeHostConnectionManager.shared.disconnect(lease). A click (wake: true) or a pane attach that lands in that gap sees the host still up and clearsletGoAt. The disconnect then closes the connection anyway. A Keep awake click fails withunavailable, or a pane loses its badge and prompts until the next read reconnects it. It heals itself, and it is rare.Fix: after the disconnect, check
letGoAtand the selection again and reconnect if the host was taken back. Or have the manager disconnect only if nothing has claimed the host since.6. A deleted host's WakefulnessModel can come back, and its poll leaks
RemoteWorkrooms.swift, inconnect:WakefulnessModel.model(forHost: id).pollWhileConnected()creates a model when none exists. If a delete callsforgetHostwhile a connect is still finishing, a fresh model starts a 10 s poll that nothing cancels. Also,RemoteHostsnever prunesletGoAt,asleepAt,connectedAt,busyReports,idleWindowsorkeyswhen a host is deleted.Fix: use a lookup that does not create the model in
connect, and clear the per-host state on delete.7. A cancelled create may not record a paid machine it left behind (investigate)
RemoteWorkrooms.create: the left-behind record is written through the CLI inside the caller's task. If that task is cancelled, the write can fail, and the only trace is the "could not record … left live" log line. Check whether a create can be cancelled in practice. If it can, write the record in aTask {}that does not inherit cancellation, asBoxdHostDriver.undoalready does.8. An old agent's box is held for a ceiling after every connect (investigate)
AgentWakefulness.swift: any status failure that is not routing-related counts as having reached the agent. That includesVCSError.backendVersionfrom an agent with no wakefulness service. So the untrusted hold starts and the box is reported busy for up to one ceiling. Decide whether an old agent should be held, or let go at once.Related, not taken here:
presencetreats onlystandbyandhibernatedas asleep. A transitional status such assuspendingwould read as awake.BoxdHostDriverTests.testAsleepIsBoxdsStandbyOrHibernatedpinsstoppedas awake on purpose. Before narrowing "awake" torunningonly, check boxd's real status list and what an ssh login does to astoppedmachine.joelmoss commentedon Oct 7, 2026
Item 3 overstated the gap.
RemoteWorkroomRoutingTests.testSelectingABoxdWorkroomKeepsItsBoxFromBeingLetGoOfandtestAnotherWindowsSelectionKeepsThisWindowsBoxAndClosingItLetsGoalready driveAppStore.selectedTargetIDanddeinit. The reviewer that raised it missed them, and I didn't check before filing.What remains untested is the restored-selection path only. That is the
selectinAppStore's reload, for a selection restored before its projects loaded (aroundAppStore.swift:3123). A test there would drive a reload of anAppStorewhoseselectedTargetIDwas set beforeprojects, then assert the box isn't let go.joelmoss commentedon Oct 7, 2026
9. Concurrent presence reads aren't shared
RemoteHosts.boxdPresencehas no in-flight sharing. Several background readers of the same unconnected host can be waiting at once: the status sweep, the file tree, history, the port-forward watch. Each one starts its ownboxd machine getbefore the first answer lands. This goes with item 1, the unanswered read that isn't cached.Fix: keep one in-flight
Taskper host and have every reader wait on it, asconnectingdoes.10. Product question: a sleeping or let-go box hides its last-known dirty state
For
.asleepand.idle,WorkroomStatus.aggregateWeightis 0 by design.RemoteWorkroomRoutingTestspins "an asleep box must not mark its project".mergeLocalStatusalso replacesdirtywith nil. So a workroom left with uncommitted work on a box the app let go shows nothing at the project level. The row's moon is its only sign.Decide: should the row keep its last-known dirty state, shown as stale, while the box sleeps?
11. The format of boxd's idle timers is measured only once
BoxdHostDriver.Seconds.parsereads a bare number or a single unit (120,120s,2m,1h). The one real reading recorded is indocs/designs/remote-workrooms.md:"auto_suspend": "120s". A compound value such as4h0m0swould read as no timer. The short-window warning would then never fire, andrevisitAfterwould fall back to 3600 s.Fix: record one real
machine get --jsonwith both timers set, including the default auto-hibernate, and pin it in a test. Log a timer that is present but fails to parse.joelmoss commentedon Oct 7, 2026
12. Stale doc comments
macapp/WorkroomApp/Core/AgentWakefulness.swift, theWakefulnessModelclass doc, reads "polled while it is on screen". A connected boxd host is now also polled when nothing on screen shows it (pollWhileConnected). The comments onpollIntervalandpoll()were updated in 31031eb, but the class doc wasn't.macapp/WorkroomApp/Core/RemoteWorkrooms.swift, theensureConnecteddoc, reads "wakefor a click (closing a pane, Keep awake)". A third caller is missing:PersistentSessionService.attachCommandcallsensureConnected(host, wake: true)when a pane attaches to a host the app let go of, which isn't a click.Low priority, also from that pass:
AgentWakefulness.minimumIdleWindow = 90follows from the Rust heartbeat'sINTERVAL_S = 60.0(vcs/crates/wr-agent/src/wakefulness/heartbeat.rs), but only prose links the two. Naming the constant in the Swift comment would let a change to one find the other.joelmoss commentedon Oct 7, 2026
13. A let-go disconnect can cut a request already in flight (P2, investigate)
RemoteHosts.observedchecks selection, port forwards and attached panes, then callsHostConnectionManager.shared.disconnect(lease).disconnectfails every pending operation on that connection withconnectionLost. The only guard isletGoGrace, 10 s after connect. A box that isn't selected reads IDLE between commands, so a long git read on it could be cut off at the next 10 s poll.Check first: does the app issue long or mutating calls against workrooms that aren't selected? If so, have
observedrefuse to let go while the lease has pending operations.14. A boxd record with no account isn't checked at delete (P3)
HostDescriptor.init(from:)decodesaccountwithtry?, so a missing or corrupt value givesDriverKey.boxd(org:, account: nil).checkOrgthen skips the account check. With another account signed in, a delete would read "not found" and treat the box as gone, leaving a paid box running. New code always writesaccount, so only hand-edited or corrupt config hits this.Fix: have
deletionKeythrowinvalidConfigurationfor a boxd descriptor withoutaccount.15. Create-progress steps can apply out of order (P3, cosmetic)
In
AppStore.swift, thesteppedclosure starts an unstructuredTask { @MainActor }for each step, so the progress ring can briefly go backwards. A late step from a finished create can also land on the next create of the same project.Fix: carry a per-create token, or a step index, and drop any step older than the last one applied.
(The reviewer's timer-format point is item 11.)
joelmoss commentedon Oct 7, 2026
16. A boxd create needs
ghonly to name the repositoryAppStore.createRemoteWorkroomnames the GitHub repository withWorkroomStatusResolver().resolveRepository(gh repo view) before it provisions anything. It throws "Couldn't find its GitHub repository with gh" whenghisn't signed in. Every remote workroom does this, Docker included, so it isn't new. For boxd, though, clone credentials come from Codaset alone, so a user signed in to Codaset and boxd but notghsees boxd enabled in the menu and then fails at create.Fix: for boxd, parse
owner/namefrom the localorigin(github.com only) and skipgh. Otherwise, gate and explain theghprerequisite in the menu.Also from that review: item 6 (the model re-created after a delete) is fixed in PR #372 for the idle-window read. Pruning the per-host dictionaries is still open.
joelmoss commentedon Oct 7, 2026
17. A stale IDLE report can let a busy box go (low likelihood)
WakefulnessModel.report(busy:)(AgentWakefulness.swift) starts its ownTaskfor each applied reading, and those tasks have no ordering. If two readings land together with opposite verdicts (IDLE, then BUSY) and the IDLE task starts second,observedsnapshots the already-incrementedbusyReportsand can let a busy box go.observedreject one older than the newest it has seen. Alternatively, send reports through one serial stream per host.[-]boxd in the app: four small follow-ups from #356's last review pass[/-][+]boxd in the app: follow-ups from #356 (PR #372)[/+]joelmoss commentedon Oct 9, 2026
Items 6 (rest), 8, 9, 13, 17 and 18 are fixed in #381 (merged 2026-10-09), and ticked off above.
#381 removed the logic these items were edge cases of: the app's let-go, its status poll, the awake ceiling and its prompt, and the idle-window warnings. Before merge, the owner also had the agent-side let-go removed, so nothing closes an idle connection now. A box an open app holds awake is the user's to free, by deleting its workroom. Item 18 is resolved by that decision rather than by making the box sleep.
Still open here: 3, 7, 10, 11, 12, 14 and 15.
🤖 Left by Claude Code