Skip to content

Phase 3: pausable command lifecycle (pause / resume / cancel)#2732

Closed
aboimpinto wants to merge 62 commits into
Hmbown:mainfrom
aboimpinto:feat/allowed-tools-phase3-fresh
Closed

Phase 3: pausable command lifecycle (pause / resume / cancel)#2732
aboimpinto wants to merge 62 commits into
Hmbown:mainfrom
aboimpinto:feat/allowed-tools-phase3-fresh

Conversation

@aboimpinto

@aboimpinto aboimpinto commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Phase 3 — Pausable Command Lifecycle (Pause / Resume / Cancel)

This PR builds on the custom slash command frontmatter from Phase 1 (PR #2326) and the hook gate from Phase 2. It adds pausable: true lifecycle support for custom slash commands: pause with ESC, type other messages while paused, resume with "continue"/"resume", and cancel with ESC twice.

Architecture

Model behavior is handled by centralized LLM evaluation. A single add_paused_evaluation_note() helper appends an evaluation note to every message sent while a paused command exists. The LLM reads the note and decides whether to continue the paused command based on the user's message — no fragile keyword matching for model decisions.

UI icon state uses minimal keyword detection in one place. submit_or_steer_message detects "continue"/"resume" to consume the paused_quarry so the WorkBench icon changes from to and the checkmark appears on completion. This is a pure UI concern — the model behavior is driven entirely by the LLM note.

Layer Keyword detection? Purpose
add_paused_evaluation_note() (centralized) No LLM evaluation note for model behavior
dispatch_user_message No Uses helper above
steer_user_message No Uses helper above
submit_or_steer_message Yes (1 place) UI icon state only (▶ and ✓)

What It Does

Frontmatter

  • pausable: true in ~/.codewhale/commands/<name>.md enables the pause lifecycle.

Pause / Resume / Cancel

  • ESC once pauses a running pausable command. A shared Arc<Mutex<bool>> flag blocks all further tool calls at the engine's pause gate (turn loop).
  • Type any message while paused — the message goes through with an evaluation note. The LLM decides whether to continue the paused command. The WorkBench keeps showing (via paused_quarry) so the user remembers the paused command.
  • "continue"/"resume" — keyword detection in submit_or_steer_message consumes paused_quarry (icon changes to ). The LLM evaluation note is still appended so the model understands the intent.
  • ESC twice cancels the paused command.
  • Cancellation notice injected into non-continue messages sent while paused.

WorkBench lifecycle indicators

  • Play — command is running (yellow)
  • Pausing — transitioning to paused (tools still draining)
  • Paused — command is on hold, waiting for resume or cancel
  • Cancelled — command was cancelled by the user
  • Finished — command completed successfully (green, via HuntVerdict::Hunted)

Files Changed

crates/tui/src/commands/user_commands.rs  |  47 +-   pausable frontmatter, state clear
crates/tui/src/core/engine.rs             |  13 +-   shared_paused flag
crates/tui/src/core/engine/handle.rs      |  19 +-   set_paused() -> Arc<Mutex<bool>>
crates/tui/src/core/engine/turn_loop.rs   |  12 +-   pause gate before tool execution
crates/tui/src/core/ops.rs                |   5 +-   SetPaused removed (dead code)
crates/tui/src/tui/app.rs                 |  20 +-   paused, pausable, paused_quarry
crates/tui/src/tui/composer_ui.rs         |  12 +-   EscapeAction::PauseCommand
crates/tui/src/tui/sidebar.rs             | 805 ++++-  WorkBench icons, 80 lifecycle tests
crates/tui/src/tui/ui.rs                  | 226 +++-  dispatch interception, LLM eval note, cancel notice
9 files changed, 1135 insertions(+), 21 deletions(-)

How to Test

Create ~/.codewhale/commands/<name>.md with pausable: true in the frontmatter.

  1. Start the command → WorkBench shows (play, yellow)
  2. ESC → WorkBench shows (paused), tool calls blocked
  3. Type "how are you?" → model responds, does NOT continue paused command, WorkBench keeps
  4. Type "can you please continue the paused command" → WorkBench shows again, model continues
  5. After completion → WorkBench shows (green checkmark)

To cancel: while paused, press ESC again → WorkBench shows

Test Results

cargo test -p codewhale-tui --bin codewhale-tui pause  -> 18 passed
cargo test -p codewhale-tui --bin codewhale-tui sidebar -> 80 passed (all sidebar tests)

Issue Alignment

Refs #1886, #1887, #1888, #1889, #1891, #1894, #1895, #1917

Builds On


Paulo Aboim Pinto

aboimpinto added 30 commits June 3, 2026 17:41
…ded (pausable/paused flags extend the cancel window)
… prevent 'Command resumed' event overriding cancel status
… sync in dispatch_user_message; direct flag clear in cancel path
… app.pausable is true (new pausable command after cancel)
…Paused / Request was Resumed / Request was Cancelled
…ds race where late engine status overwrites cancel/resume; add guard in Event::Status handler; update test to verify guard
Comment thread crates/tui/src/tui/ui.rs Outdated
Comment thread crates/tui/src/commands/user_commands.rs Outdated
Comment thread crates/tui/src/commands/user_commands.rs
Comment thread crates/tui/src/tui/ui.rs
Comment thread crates/tui/src/commands/user_commands.rs

@aboimpinto aboimpinto left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All clippy warnings resolved (collapsible_if, unnecessary_map_or, manual_pattern_char_comparison, unnecessary_cast in shell.rs). The git stash snapshot mechanism is acknowledged as a best-effort prototype with known limitations (no restore, sync call). Resume detection was hardened with word-boundary checks (contains " continue "). Manual lock handling in CancelRequest uses direct flag set to avoid Op race. The try_lock for todos/plan clearing is best-effort (logs and continues on failure).

Comment thread crates/tui/src/tui/ui.rs Outdated
@Hmbown

Hmbown commented Jun 4, 2026

Copy link
Copy Markdown
Owner

this is such a smart update @aboimpinto - wow. thank you for your time and effort!

@aboimpinto

Copy link
Copy Markdown
Contributor Author

@Hmbown almost finished ...

Comment thread crates/tui/src/tui/ui.rs

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aboimpinto has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aboimpinto has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aboimpinto has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@aboimpinto aboimpinto marked this pull request as ready for review June 4, 2026 09:05

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aboimpinto has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Hmbown added a commit that referenced this pull request Jun 5, 2026
…and-mvp

Harvest pausable custom command MVP from #2732
@Hmbown

Hmbown commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Thanks @aboimpinto for the thoughtful lifecycle work here. We landed the safe pausable-command MVP as #2803, merged in 8fe89006700903d1d91868e5e59f8b243f731ec3, with credit preserved in the harvest PR/changelog and a mappable Co-authored-by: aboimpinto <1231687+aboimpinto@users.noreply.github.com> trailer.

The slice that landed keeps pausable: true custom-command frontmatter, the TUI pause/cancel state, and the engine-side pause gate before future tool execution. I intentionally did not carry forward the prototype rollback/stash path because the branch could run git stash push --include-untracked without a matching restore path, which would be risky for contributor/user worktrees.

I am closing this PR as superseded by #2803 so the release train can keep moving, but the broader hook-layer lifecycle intent is still useful future work. Thanks again for pushing this direction forward.

@Hmbown Hmbown closed this Jun 5, 2026
timothybrush pushed a commit to timothybrush/DeepSeek-TUI that referenced this pull request Jun 8, 2026
Harvested from PR Hmbown#2732 by @aboimpinto.

Parse pausable frontmatter for custom slash commands, add a narrow engine pause gate before tool execution, and preserve paused command state across separate messages until explicit resume, cancel, terminal completion, or a new command.

Also centralize strict resume-message detection with negative coverage for deferred or negated phrases, and keep rollback/stash/worktree mutation behavior out of this slice.

Co-authored-by: aboimpinto <1231687+aboimpinto@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants