## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The task composer is where operators direct running agents. > - Operators need to stop work without leaving the conversation. > - Existing pause controls already hold task trees and interrupt both runner types. > - This pull request connects the composer to those controls and removes repeated feedback. > - Operators can pause work quickly and still queue messages while agents run. ## Linked Issues or Issue Description **What existing behavior does this improve?** Task pause, resume, and cancellation in the task page and composer. **Current behavior** The empty composer cannot stop a running task. Task controls require extra confirmation and reason text. Pause can show several notifications for the task already on screen. **Proposed behavior** Show Stop while this task runs and the composer is empty. Text or attachments switch it to Send. Stop and the menu use the same manual pause hold. Parent pauses include descendants. Keep task cancellation in the menu with a compact confirmation. Show one quiet pause row and gray cancelled-run details. **Reason and benefit** Operators can interrupt execution with one click. Drafts and queued messages keep their existing behavior. The UI waits for actual termination, including native cancellation acknowledgment. **Breaking changes** No endpoint, schema, or task-status change. Pause no longer asks for confirmation or a reason. Resume now honors the existing wake-agents option. Task notifications are suppressed for the task and subtree currently in view. Related UI work: #8228 changes navigation and composer shortcuts. This PR covers execution controls. No duplicate Stop-button PR was found. The change improves existing controls and does not duplicate a roadmap milestone. ## What Changed - Add Stop, pending feedback, duplicate-click protection, and inline errors to the composer. - Share the pause mutation across the composer, active-run controls, and menu. - Poll affected runs after a pause request. Require native cancellation acknowledgment. - Remove pause confirmation and shared reason fields. Reduce cancel confirmation to its task count and actions. - Honor wake-agents for executable tasks only. Preserve the pause when recovery review is needed; show partial wake failures inline. - Preserve explicit legacy reconciliation decisions while their continuation waits for dispatch. - Suppress notifications for visible task trees. Use quiet pause and cancellation feedback. - Add interactive stories using production controls and native/legacy end-to-end tests. ## Verification - User reviewed the running feature and revised Storybooks in the browser. - Rebased focused checks passed: 295 original targeted tests, 161 updated route/page/notification/status tests, and 26 recovery integration tests. - Both isolated runner journeys pass on the final revision (1.7 minutes). Coverage includes queueing, parent and child interruption, persisted holds, no automatic continuation, reconciled resume, cancellation, terminal exclusions, and no Stop toast. - Native coverage uses real runnerd with a deterministic provider fixture. Legacy coverage checks actual process termination. Live hosted-provider execution was not tested. - Repository typecheck and build, Storybook build, and token gates passed after rebase. The final server typecheck/build also passed. - The broad local run completed its general-server stage with 7,219 passing tests, 48 skipped, and two failures from cached pre-fix source and a stale native provider fixture. Both failed tests pass in fresh final-head reruns after rebuilding the fixture; the script did not continue to its later local stages. CI runs all test groups on the final revision. - Final revision: all 31 applicable CI checks passed; Storybook visual regression was skipped by its workflow conditions. Greptile: 5/5, zero unresolved comments. - Review `Tasks / Execution Controls` in Storybook. Type and clear a draft, stop a run, expand cancellation details, and test the menu on desktop and mobile. ## Risks - Stop pauses descendants for a parent task. This is the existing pause contract. - A held task can remain active if interruption fails. The UI shows an error instead of claiming termination. - Resume can start multiple assignees when wake-agents is selected. Backlog, blocked, and terminal tasks stay excluded. Existing execution reconciliation remains mandatory where required; Resume never invents action-outcome evidence. - Notification suppression uses the visible task and cached subtree. Notifications for unrelated work remain enabled. ## Model Used OpenAI GPT-6 through Codex. The exact runtime snapshot and context-window limit are not exposed in this session. Used reasoning, tool calls, code execution, and browser inspection. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
8.1 KiB
Composer Stop and task controls
The empty composer shows Stop while this task has a live execution and the viewer can manage task controls. Stop creates the same manual pause hold as Pause work / Pause subtree in the task menu. A parent pause includes its descendants. Cancellation remains a separate menu action.
Text (after trimming) or attachments switch the button back to Send. Uploading and failed attachments retain their existing restrictions. Keyboard submission never invokes Stop. Queued-message editing and structured interactions keep their existing actions, and text entered while stopping remains in the draft.
Pause dispatches without a preview dialog or reason. The button stays pending while affected run state is checked; native cancellation must be acknowledged. A saved hold with unconfirmed termination produces an error rather than a success claim. The cancellation dialog requires a valid preview and excludes terminal tasks. Resume/restore retain the optional wake-agents checkbox.
Resume and execution recovery
Resume releases a hold. Waking agents is optional and only applies to tasks in
todo, in_progress, or in_review; parked and terminal tasks stay untouched.
The current execution-recovery policy requires verified outcomes before a stopped
provider can restart. If any affected task still needs that reconciliation,
Resume with wake enabled returns an inline error and preserves the pause. The
operator can release the pause without waking agents, then use the existing
execution-reconciliation flow after reviewing the stopped run. Resume does not
claim that unknown provider actions completed or were never performed.
A completed release remains successful if a best-effort wake fails. Its response
includes optional wakeFailures, the page reports them inline, and remaining
eligible tasks still receive their wake requests. No new endpoint is introduced.
The deterministic E2E fixtures prove interruption, then record their known lack
of external effects through the existing reconciliation API before continuing.
Quiet task feedback
The visible task/subtree does not produce duplicate state toasts. Its live
notifications are suppressed while foregrounded, including descendant runs;
unrelated and background work retains notifications. Tree-control results use
inline state, and failures stay in the composer, page, or confirmation dialog.
The pause row contains only “Subtree is paused.” (or “Task is paused.”) and
Resume. Expected cancellation uses a muted gray disclosure with optional details.
This is recorded as a product rule in DESIGN.md.
The follow-up passed 213 focused tests, both isolated runner E2E journeys (including no-toast assertions), UI typecheck/build, token gates, and Storybook build. Paused, expanded cancellation, Stop without toasts, mobile, and light stories were inspected in the browser.
Storybook
Run from the worktree:
pnpm --filter @paperclipai/ui exec storybook dev -p 6016 -c storybook/.storybook --no-open
Open http://localhost:6016/?path=/story/tasks-execution-controls--running-empty.
The Tasks / Execution Controls stories compose the production composer and
menu/dialog controls together. They cover text switching, attachment-only,
idle, stopping, paused, errors, cancellation preview/loading, and mobile/light
presentations. The Storybook state transitions simulate requests; runner
verification belongs to the isolated browser suite below.
Automated verification
pnpm exec vitest run --project @paperclipai/ui ui/src/components/task-chat/TaskChatComposer.test.tsx ui/src/components/TaskChatThread.test.tsx ui/src/pages/IssueDetail.test.tsx ui/src/lib/wait-for-stopped-runs.test.ts
pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-tree-control-routes.test.ts
pnpm check:token-gates
pnpm build-storybook
pnpm -r typecheck
pnpm test:run
pnpm build
The component/page tests cover whitespace, attachments and upload restrictions, permissions, keyboard submission, queue edits, duplicate clicks, draft preservation, shared pause requests, compact cancellation, and visible errors. Stop verification tests include continued execution, native acknowledgment, network failures, and hung status requests. Route tests cover pause dispatch, authorization, cancellation, and opt-in resume wakeups with terminal/company exclusions.
Isolated browser acceptance
Legacy process coverage needs no provider credentials:
pnpm exec playwright test --config tests/e2e/playwright-composer-stop.config.ts
To include native execution, build the real runner and deterministic Codex protocol fixture from this checkout, then point the suite at their absolute paths:
cargo build --manifest-path packages/paperclip-runner/runner/Cargo.toml --bin paperclip-runnerd --bin fake-codex-app-server
PAPERCLIP_STOP_FAKE_CODEX="$PWD/packages/paperclip-runner/runner/target/debug/fake-codex-app-server" \
PAPERCLIP_RUNNER_BINARY="$PWD/packages/paperclip-runner/runner/target/debug/paperclip-runnerd" \
pnpm exec playwright test --config tests/e2e/playwright-composer-stop.config.ts
The suite boots a disposable local-trusted instance on port 3199 (override with
PAPERCLIP_E2E_PORT). It never attaches to an existing server. Native coverage
is explicitly skipped without the fixture; it must not use a logged-in provider
as a fallback. Test companies are archived during cleanup.
For each runner, the journey starts a parent, child, and unrelated task, plus a terminal child. It sends while running and verifies the durable queue, clicks Stop, verifies interruption and the persisted hold, and observes three ten-second scheduler intervals without continuation. It resumes with wakeups, pauses from the menu, dismisses and then confirms cancellation, and verifies terminal-task exclusions and unrelated execution.
Timing attachments distinguish click-to-request from request-to-observed-stop.
Native proof requires provider turn/start before the click, turn/interrupt
after it, and durable cancellation acknowledgment. Legacy proof checks the
actual parent and child PIDs have exited with a one-second configured grace
period. HTTP success alone is insufficient.
For a release with real providers, repeat while an actual long-running tool is active, confirm the tool's own process/output stops, and verify a queued message is consumed on continuation. The deterministic provider exercises the native transport and cancellation protocol, not external provider behavior or every tool's process cleanup. Preserve these limits in any test report.
Recorded acceptance run (2026-09-09)
Both isolated browser journeys passed. Legacy Stop dispatched after 214 ms and observed both runs stopped 155 ms after dispatch; native dispatched after 212 ms and observed stop 320 ms later. These are single local observations including browser automation overhead, not latency guarantees. Native used the real runnerd and the repository's deterministic Codex protocol fixture. Real hosted provider/tool cleanup remains a release acceptance check.
Repository typecheck, production build, Storybook build, token gates, targeted
UI tests, and tree-control route tests passed. The broad UI run passed 5,491
tests with one five-second timeout in an unchanged IssuesList test; rerunning
that file passed all 46 tests. The repository test run encountered 17 failures
in unchanged suites, all reproduced in the original checkout:
server/src/__tests__/workspace-runtime.test.ts: 2 failures.server/src/services/workspace-runtime-exposure.test.ts: 7 failures.server/src/__tests__/execution-workspace-runtime-control-conflict.test.ts: 4 failures.server/src/__tests__/workspace-instance-cleanup.test.ts: 1 failure.server/src/__tests__/company-skills.test.ts: 2 failures.server/src/__tests__/worktree-seed-server-spawn.test.ts: 1 failure.
These baseline failures prevent a green repository-wide test result. The broad run was stopped after more than 30 minutes in its serial server lane once these failures were independently reproduced. Later full-suite groups did not run. The full UI suite and the feature's server route suite were run separately as described above.