Skip to content

fix(tui): always dismiss stale forms#36588

Open
kitlangton wants to merge 2 commits into
v2from
dismiss-stale-form
Open

fix(tui): always dismiss stale forms#36588
kitlangton wants to merge 2 commits into
v2from
dismiss-stale-form

Conversation

@kitlangton

Copy link
Copy Markdown
Contributor

What

Make Escape an unconditional local exit from a form prompt, even when the background server has restarted or can no longer find the form.

Before / After

Trigger: The TUI receives and displays a pending form, then the background server restarts. The form is process-local, so the replacement server no longer has its frm_… ID, while the TUI still has the old form in client state.

Before: Pressing Escape only sent form.cancel to the server. The TUI waited for a form.cancelled event before removing the prompt. The restarted server returned FormNotFoundError, emitted no cancellation event, and the stale prompt remained onscreen. Repeated Escape presses repeated the same failed request, leaving no route back to the composer.

After: Escape removes the form from TUI state first, so the prompt closes immediately and the composer becomes available regardless of server state. The TUI then attempts server cancellation as best-effort cleanup. Already missing, settled, or session-missing responses are terminal and ignored; unexpected failures still surface a toast.

How

  • packages/tui/src/context/data.tsx owns local form dismissal alongside form listing and refresh.
  • packages/tui/src/routes/session/form.tsx calls local dismissal before the cancellation request and routes every form-level Escape path through the same function.
  • Session and home routes bind FormPrompt dismissal to the shared data store.
  • The rendered TUI regression returns a real FormNotFoundError, presses Escape, and verifies the prompt disappears while cancellation is still attempted.
  • Data-context coverage verifies local dismissal mutates the production form store.
sequenceDiagram
    participant U as User
    participant T as TUI
    participant S as Restarted server
    U->>T: Escape
    T->>T: remove stale form locally
    T-->>U: restore composer immediately
    T->>S: best-effort form.cancel(frm_old)
    S-->>T: FormNotFoundError
    T->>T: ignore terminal absence
Loading

Scope

This changes TUI dismissal behavior only. It does not make process-local forms durable across server restarts or change server form lifecycle semantics.

Testing

  • cd packages/tui && bun run test test/cli/tui/form.test.tsx test/cli/tui/data.test.tsx (35 passed)
  • cd packages/tui && bun typecheck
  • Push hook: repository-wide Turbo typecheck, 31 packages passed.
  • git diff --check

@kitlangton kitlangton self-assigned this Jul 13, 2026
@kitlangton kitlangton marked this pull request as ready for review July 13, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant