mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 19:28:46 +01:00
## 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>
156 lines
8.1 KiB
Markdown
156 lines
8.1 KiB
Markdown
# 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:
|
|
|
|
```sh
|
|
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
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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:
|
|
|
|
```sh
|
|
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.
|