Skip to content

vscode: guarded-command feedback is silent after first click — replace setupToastShown one-shot suppression with modal-first / ephemeral-after pattern #989

@amrmelsayed

Description

@amrmelsayed

Problem

When the CLI preflight (#791) determines the environment is broken (missing or outdated), the first click on a guarded command produces a modal warning toast with a Run Setup action. Every subsequent click within the same session is silent. The setupToastShown flag at packages/vscode/src/preflight/preflight.ts:245-261 suppresses repeat toasts for the rest of the session, resetting only when the user explicitly runs Codev: Recheck CLI and the recheck confirms status === 'ok'.

The intent was anti-spam. The defect is lack of point-of-action feedback. After the first click, the user clicks Spawn Builder, Approve Gate, Send Message, or any of the 13 other guarded commands and gets no signal whatsoever. The click registered with the guard, the guard rejected it, the helper bailed silently. From the user's perspective, the four scenarios below look identical:

  1. The command silently no-op'd (what's actually happening)
  2. The click missed the menu item
  3. The command ran but didn't visibly do anything
  4. The extension is hung

All four read as "nothing happened". The toast was the only signal that disambiguated them, and the suppression eliminates it.

Why this is the wrong default

The original design intent (don't spam modal toasts on rapid clicks) is sound. The execution overshot: it traded modal spam for zero feedback. The right shape is attenuated feedback, not absent feedback.

Point-of-action feedback is the load-bearing principle. Asking the user to notice a state indicator elsewhere (sidebar Status row, status-bar item, etc.) is asking the UI to push the work back onto the user. The fix needs to keep the feedback co-located with the action.

Proposed fix

Two-stage feedback that preserves point-of-action signal without modal spam:

First click while state is bad: modal warning toast

Unchanged from today. Full showWarningMessage with the Run Setup action button. The user is being told the state for the first time; modal is appropriate.

Subsequent clicks within the session: ephemeral status-bar message

VS Code has vscode.window.setStatusBarMessage(text, durationMs). It shows a brief temporary line at the bottom-left for N seconds, no action button, no modal interrupt. VS Code itself uses this pattern for things like "Saving..." / "Loaded N files".

Something like:

vscode.window.setStatusBarMessage(
  `Codev: CLI ${cachedStatus === 'outdated' ? 'outdated' : 'not installed'} — run Codev: Recheck CLI when ready`,
  4000,
);

User gets immediate, visible, co-located confirmation that the click registered AND the same problem still applies. Not a modal interrupt; doesn't break flow.

Flag reset semantics

Unchanged. The flag still resets when recheckCli confirms ok. The only change is what fires on subsequent suppressed clicks.

Refactor for reusability (composes with #983)

This issue's primary work is the per-click feedback pattern. Worth designing the implementation as a reusable helper rather than inline logic, because the same shape is needed by #983 (Tower running-vs-installed version divergence). When #983 ships, it should call the same helper, with the helper branching on which preflight dimension is currently broken (CLI version vs Tower version).

Suggested shape:

export function showPreflightFeedback(state: PreflightState): void {
  // First call this session for the current bad state: modal
  // Subsequent calls: ephemeral status-bar message
  // Wording derived from state (CLI missing / outdated / Tower stale / etc.)
}

The current showSetupRequiredToast becomes a thin wrapper or merges into the helper.

Acceptance

  • Every click on a regCli-guarded command produces visible feedback at point of action while the preflight state is missing or outdated. No silent no-ops.
  • First click in a session with a bad state: modal warning toast with Run Setup action (unchanged from today).
  • Subsequent clicks in the same session: ephemeral status-bar message naming the same state, for a short duration (around 3-4 seconds).
  • When Codev: Recheck CLI confirms ok, the per-session counter resets; the next click after the state breaks again restarts the modal-first pattern.
  • No regression to the happy-path (state is ok or pending → command runs normally, no feedback noise).
  • Implementation factors the feedback dispatch into a helper (showPreflightFeedback or equivalent) that vscode + tower: detect installed-vs-running Tower version divergence; preflight needs an in-memory version probe, not just codev --version #983 can call when its Tower-version branch needs to surface feedback, without re-inventing the suppression logic.

What this isn't

Related

Metadata

Metadata

Assignees

Labels

area/vscodeArea: VS Code extension

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions