Skip to content

Escape should rely on Lash's FIG-1573 re-deferral instead of host-side draft replay #5

Closed

Description

@SamGalanakis

On manual interrupt the CLI first cancels every pending active-turn input (interactive/input_handling/shortcuts.rs retire_pending_active_turn_inputs), then, after the interrupted commit, re-enqueues process-local copies as NextTurn with interrupt-replay:* ids (interactive/mod.rs defer_interrupted_active_turn_drafts, App::queues.active_turn_drafts).

Lash main already does this atomically (FIG-1573): the cancel commit carries RuntimeCommit::deferring_interrupted_turn_inputs(turn_id) and a turn that ends without committing runs defer_orphaned_turn_inputs_after_teardown, relabelling undelivered ActiveTurn rows as DeferredNextTurn. Cancelling the rows first makes them un-repairable (orphaned_active_turn_input_is_repairable requires PendingActive/Accepted), so the CLI reopens the crash window Lash closed and only preserves what this process remembers.

Do: delete active_turn_drafts, retire_pending_active_turn_inputs, defer_interrupted_active_turn_drafts and the replay-id scheme; keep only request_turn_cancel + token cancel; keep draft_presentations (presentation cache) keyed by Lash's input ids. Verify the foreground turn holds the session-execution lane so the deferral lands in the cancel commit rather than the drain backstop (if lane-less, document the latency). PTY witness: steer mid-turn, Escape, expect ◇ Queued for next turn with the steer text and exactly one provider request containing it afterwards.


Prospect addendum (2026-08-23, see /workspace/notes/prospect-steer-cancel-2026-08-23.md): peer consensus (pi TUI restoreQueuedMessagesToEditor, pi runtime2 abort-drain design) is that unsent steers return to the user on abort rather than auto-firing next turn. Implement that as host policy on top of Lash's deferral: after the interrupted commit, read pending rows in state DeferredNextTurn addressed to the dead turn, tombstone them via cancel_pending_turn_inputs, and restore their text into the editor. No host-retained drafts; a crash in between leaves the rows DeferredNextTurn, which --resume must display (never silently discard). Open check: whether the foreground turn holds the session-execution lane (otherwise deferral lands at the drain backstop, not the cancel commit).

Blocked on Lash FIG-1923 (cancel disposition Defer | Drop + outcome naming affected inputs). Target shape once it lands: Escape = request_turn_cancel(..).undelivered(Drop), read the outcome's dropped inputs, restore their text to the editor. Until then the current host-side replay stays.

Activity

  1. SamGalanakis commented on Aug 25, 2026

    @SamGalanakis
    OwnerAuthor

    Landed on upgrade/lash-main (PR #4). Escape is now a durable TurnCancelRequest with an explicit TurnCancelDisposition::Drop for undelivered inputs, submitted through core.turn_work_driver() against the tracked physical turn id (direct turns and queue drains both) — see 9ba5a7b for the cutover that deleted the host-side draft-replay machinery (active_turn_drafts, retire_pending_active_turn_inputs, defer_interrupted_active_turn_drafts) and addc00c for the follow-up that keeps the TUI responsive during cancellation (outcome read from the settled TurnReport.cancel_input_outcome) and restores dropped input to the editor. Upstream support arrived via FIG-1923 (lash #696).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions