Symptom
Clicking a builder row in the Codev sidebar produces a warning toast:
Codev: No active terminal for <builder-id>
…then nothing else happens. The builder row stays in the sidebar (looking normal), but you can't open its terminal from the click. The user is left with a dead-end UX: no indication of what's wrong, no in-extension affordance to recover.
The warning fires at packages/vscode/src/terminal-manager.ts:201 inside openBuilderByRoleOrId:
if (!builder?.terminalId) {
vscode.window.showWarningMessage(`Codev: No active terminal for ${roleOrId}`);
return;
}
So Tower's getWorkspaceState returns a builder record matching the clicked row, but that record's terminalId is null or empty. The overview (which the sidebar renders from) and the workspace-state (which the terminal opener queries) disagree on whether this builder has a live terminal session.
Why the disagreement happens
Three known triggers, in order of likelihood:
- Tower restarted. Tower's PTY session registry is in-memory; the disk-persisted builder records survive restarts but the session IDs that bind a builder to a live PTY don't. Sidebar still shows the builder (filesystem-sourced); clicking fails because
terminalId is gone.
- Terminal session died without the builder being cleaned up. PTY child crashed, WebSocket disconnected past the GC timeout, network blip dropped the session and Tower forgot it. Builder record persists; terminal record vanishes.
- Race window during spawn or recover. Briefly between "builder registered" and "terminal session created" the overview may report the builder without a
terminalId. Self-corrects on the next overview tick.
(1) and (2) are persistent and require user action. (3) is transient and self-heals.
Why it matters
The warning is correct (something IS wrong) but the UX is unactionable. The user has to know that:
afx workspace recover exists and is the right tool
- They have to run it from the workspace root, not inside a worktree
- It only works if the builder process itself is still alive somewhere
A first-time user (or any user mid-flow) hits the toast and has no obvious next step. The sidebar row remains looking healthy, which compounds the confusion. The bug-class is silent state divergence with a downstream "polite" failure — exactly the shape the v3.1.7 #916 fix was designed to head off for the overview case, but the same divergence in the opposite direction (overview populated, individual fields stale) wasn't covered there.
Proposed improvements (plan-approval picks the layer)
Five plausible directions, ranged from "polish the dead-end" to "fix the underlying divergence":
- Better error message + recovery suggestion. Replace the bare toast with something like "Builder #X's terminal session is gone (likely Tower restart). Run
afx workspace recover from the workspace root to revive it, or cleanup if it's no longer needed." Cheap; pure vscode.
- In-extension recover affordance. Add a
Recover button on the toast that invokes afx workspace recover for that specific builder (or the whole workspace). One-click instead of "go look up the right command". Pure vscode plus a small CLI integration.
- Sidebar visual signal. Builders without a live terminalId render with a distinct icon (e.g.,
unlink or circle-slash) so the user can see before clicking that the session is dropped. Pure vscode.
- Auto-recover on extension activation. Detect on load that there are builders without terminalIds and either run recovery or prompt the user. Stronger UX but a behavior decision (auto-runs vs prompts) that needs plan-gate.
- Root-cause fix: persist Tower's session registry. Survive restarts so the disk record and the runtime record don't diverge in the first place. Largest scope; addresses cause (1) but not (2) or (3).
(1) and (2) compose cleanly and could ship together as a v1; (3) is independent and can layer on; (4) and (5) are bigger investments worth deferring.
Acceptance (loose, pending plan-gate)
What this isn't
Related
- #915 —
afx workspace recover semantics for previously-cleaned-up builders.
- #916 — sidebar last-known-good fix (shipped in v3.1.7). Adjacent state-divergence class, opposite direction.
packages/vscode/src/terminal-manager.ts:180-208 — openBuilderByRoleOrId (where the warning lives).
Symptom
Clicking a builder row in the Codev sidebar produces a warning toast:
…then nothing else happens. The builder row stays in the sidebar (looking normal), but you can't open its terminal from the click. The user is left with a dead-end UX: no indication of what's wrong, no in-extension affordance to recover.
The warning fires at
packages/vscode/src/terminal-manager.ts:201insideopenBuilderByRoleOrId:So Tower's
getWorkspaceStatereturns a builder record matching the clicked row, but that record'sterminalIdis null or empty. The overview (which the sidebar renders from) and the workspace-state (which the terminal opener queries) disagree on whether this builder has a live terminal session.Why the disagreement happens
Three known triggers, in order of likelihood:
terminalIdis gone.terminalId. Self-corrects on the next overview tick.(1) and (2) are persistent and require user action. (3) is transient and self-heals.
Why it matters
The warning is correct (something IS wrong) but the UX is unactionable. The user has to know that:
afx workspace recoverexists and is the right toolA first-time user (or any user mid-flow) hits the toast and has no obvious next step. The sidebar row remains looking healthy, which compounds the confusion. The bug-class is silent state divergence with a downstream "polite" failure — exactly the shape the v3.1.7
#916fix was designed to head off for the overview case, but the same divergence in the opposite direction (overview populated, individual fields stale) wasn't covered there.Proposed improvements (plan-approval picks the layer)
Five plausible directions, ranged from "polish the dead-end" to "fix the underlying divergence":
afx workspace recoverfrom the workspace root to revive it, or cleanup if it's no longer needed." Cheap; pure vscode.Recoverbutton on the toast that invokesafx workspace recoverfor that specific builder (or the whole workspace). One-click instead of "go look up the right command". Pure vscode plus a small CLI integration.unlinkorcircle-slash) so the user can see before clicking that the session is dropped. Pure vscode.(1) and (2) compose cleanly and could ship together as a v1; (3) is independent and can layer on; (4) and (5) are bigger investments worth deferring.
Acceptance (loose, pending plan-gate)
terminalIdis missing on a clicked builder row, the user gets a clear signal of what's wrong and what to do next, not just a bare warning.afx workspace recoversemantics.What this isn't
afx workspace recoveritself — that's tracked separately at #915.Related
afx workspace recoversemantics for previously-cleaned-up builders.packages/vscode/src/terminal-manager.ts:180-208—openBuilderByRoleOrId(where the warning lives).