paperclip/server/src
Dotta c9e3bb7ca4
fix: preserve queued work after native Stop and honor steering support (#13354)
## Thinking Path

> - Paperclip lets people manage AI agents and their tasks.
> - The runner owns execution, while the task keeps user instructions
and status.
> - Stop must stop the current response without losing instructions that
the user already sent.
> - The queue stored its original reason inside saved context. Recovery
checked the outer deferred reason and left the message waiting.
> - Claude also exposed Steer through a shared method even though its
driver did not support it. A rejected request could remove its own error
row.
> - This pull request keeps queued work until execution has stopped,
uses the driver's real capability, and preserves completion event order.
> - Users can continue work without repairing task state or repeating
messages.

## Linked Issues or Issue Description

Refs #13338. Related recovery work: #13353.

**What happened?**

A message sent during a native run stayed queued after Stop. Claude
exposed an unsupported Steer action. A steering failure could hide the
queued row and its error. A terminal event could also precede the final
provider result, and subtree Stop omitted the board actor.

**Expected behavior**

Stop ends the current execution. Once Paperclip proves that execution
has stopped, it delivers the saved instruction once through normal
admission. Pause and recovery holds still prevent dispatch. Unsupported
controls stay disabled, and a rejected action leaves an actionable error
visible. Final results precede terminal events.

**Steps to reproduce**

1. Start a Claude or Codex task that writes a file and then waits.
2. Send a follow-up instruction while it runs.
3. Press Stop. Check that the queued instruction runs once and preserves
the file.
4. Check Claude's Steer control and simulate a server rejection on the
only queued message.

## What Changed

- Recover saved native comments after acknowledged Stop using their
original wake reason.
- Require durable remote termination receipts or verified local process
termination before dispatch.
- Preserve actor identity, queued-message deduplication, Pause, and
recovery gates.
- Derive steering support from the driver descriptor and reject
unsupported calls.
- Keep the queue mounted until a steering request succeeds so its error
remains visible.
- Emit provider results before terminal events and pass the board actor
into subtree Stop.
- Document Stop and steering behavior.

## Verification

- Final-head continuation suite: 104 passed, after failing regressions
for saved wake reasons, cleanup proof, and deduplication of every queued
message. Steering UI: 121 passed. Driver capability: 26 passed. Runner
backend/transport: 205 passed; Rust library: 285 passed.
- Real Claude and Codex browser journeys both preserved the saved file,
delivered the queued instruction once after Stop, and reached Done with
exactly two total runs. The process Stop browser fixture also passed.
- Local full repository typecheck and build passed on `afaa35139`;
server typecheck and the affected 104-test suite passed after the final
queue changes. Token gates passed. Final-head CI verifies the complete
integrated source.
- Local aggregate evidence has explicit limits: the general-server
invocation overlapped the queue fixes and finished with 11,989 passed, 2
failed, and 80 skipped; both failures are covered by the final 104-test
pass. The UI and CLI then passed all 6,184 and 485 tests; the complete
145-file serialized rerun passed all 2470 tests. The shared-package lock
fixture passed unchanged on rerun, but the package phase subsequently
stopped at an embedded-Postgres bootstrap resource failure. No single
pristine green local full aggregate is claimed.
- Greptile reviewed `fa66e2bd5` at [5/5 with no unresolved
findings](https://github.com/paperclipai/paperclip/pull/13354#issuecomment-5650334242).
[Final-head CI completed
successfully](https://github.com/paperclipai/paperclip/actions/runs/34733781888/attempts/2):
33 successful checks, 2 conditional skips, including all server,
package, UI, browser, runner, typecheck, and build gates. The first
attempt hit a preview-readiness/port-collision fixture; its unchanged
local control passed 25 tests with 3 skips, and one supported unchanged
CI retry passed the affected shard and aggregate gates.

## Risks

- Queue recovery must never overlap an old execution. Unknown cleanup
state remains blocked.
- Driver descriptors are now authoritative for steering; a wrong
descriptor disables the action instead of attempting it.
- No schema migration or historical status reconciliation is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, browser
testing, and tool use. The exact hosted model ID and context-window size
are not exposed in this task.

## 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
#` 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>
2026-09-12 22:29:54 -05:00
..
__tests__ fix: preserve queued work after native Stop and honor steering support (#13354) 2026-09-12 22:29:54 -05:00
adapters fix: repair runner configuration, macOS execution, and artifact galleries (#13062) 2026-09-08 19:10:09 -05:00
auth feat(runner): add Codex-native application integration (#12591) 2026-08-31 14:38:38 -05:00
built-ins/agents Remove cheap model profiles (#12683) 2026-09-01 14:57:38 -05:00
http feat: add experimental native chat connectors (#13038) 2026-09-10 10:06:45 -05:00
lib perf(server): reduce issue detail request overhead (#10414) 2026-08-11 14:39:23 -04:00
middleware fix(server): stop reporting expected managed-cloud transients to Sentry (#13323) 2026-09-12 11:15:43 -07:00
modules fix: preserve runner recovery, warm sessions, and task outcomes (#13338) 2026-09-12 19:41:15 -05:00
onboarding-assets fix(onboarding): make chief-of-staff hiring reliable (#13317) 2026-09-12 12:59:42 -05:00
realtime feat: add experimental native chat connectors (#13038) 2026-09-10 10:06:45 -05:00
routes fix: preserve queued work after native Stop and honor steering support (#13354) 2026-09-12 22:29:54 -05:00
secrets feat(secrets): write through external values and deep-link details (#10196) 2026-07-27 19:08:07 -05:00
services fix: preserve queued work after native Stop and honor steering support (#13354) 2026-09-12 22:29:54 -05:00
storage feat(run-logs): durable run-log store via object-storage mirror (#8984) 2026-07-14 15:45:39 -07:00
types feat(server): accept a Cloud control assertion on the task-drain endpoint (#13125) 2026-09-10 11:56:28 -07:00
vendor/paperclip-runner fix: preserve runner recovery, warm sessions, and task outcomes (#13338) 2026-09-12 19:41:15 -05:00
agent-auth-jwt.ts fix(server): align agent run JWT default TTL with documented 48h default (#10176) 2026-08-12 16:44:20 -07:00
app.ts fix: enable isolated subscription login on authenticated self-hosted instances (#13344) 2026-09-12 23:06:55 +00:00
attachment-types.ts feat(channels): add experimental iMessage Photon (#13299) 2026-09-12 15:23:50 -05:00
board-claim.ts [codex] Add agent permissions and controls plan (#6386) 2026-05-22 08:12:52 -05:00
build-commit.ts fix(server): preserve source SHA without Git metadata (#9638) 2026-07-15 20:03:52 -05:00
build-version.ts fix(server): stamp the real build version into images instead of the package.json placeholder (#10257) 2026-07-25 10:06:28 -07:00
chat-webhook-public-url.ts feat: add experimental native chat connectors (#13038) 2026-09-10 10:06:45 -05:00
cloud-ui-snippet.ts feat: accept a base64-encoded Cloud UI snippet (#13245) 2026-09-11 14:13:11 -07:00
config-file.ts fix(config): preserve extensions and guard invalid repairs (#11005) 2026-08-07 00:41:19 -05:00
config.ts feat: add experimental native chat connectors (#13038) 2026-09-10 10:06:45 -05:00
db-errors.ts fix(issues): make DELETE /api/issues/:id succeed for issues with dependents (#11331) 2026-08-13 12:02:15 -07:00
dev-native-runner-status.ts feat(runner): integrate Codex native execution (#12616) 2026-08-31 22:51:17 -05:00
dev-runner-worktree.ts feat(workspaces): sign the workspace login handoff and gate readiness (#11671) 2026-08-19 02:37:02 -05:00
dev-server-status.ts fix(runner): recover native sessions across restarts (#12845) 2026-09-04 15:03:53 -05:00
dev-watch-ignore.ts fix(server): ignore sibling worktrees in dev watch (#11074) 2026-08-07 18:30:16 -07:00
embedded-postgres-owner.test.ts fix: preserve runner recovery, warm sessions, and task outcomes (#13338) 2026-09-12 19:41:15 -05:00
embedded-postgres-owner.ts fix: preserve runner recovery, warm sessions, and task outcomes (#13338) 2026-09-12 19:41:15 -05:00
embedded-postgres-supervisor.ts fix(workspaces): recover degraded runtime databases (#11651) 2026-08-18 17:40:54 -05:00
env-file-policy.ts feat(cli): add isolated test-drive command (#12894) 2026-09-05 09:33:38 -05:00
errors.ts feat(artifacts): bridge Markdown work products into the document review surface (#11822) 2026-08-20 17:28:01 -07:00
first-admin-claim.ts [codex] Add private browser first-admin claim flow (#6755) 2026-05-27 21:15:01 -10:00
home-paths.ts feat(server): thread plural referenced-project workspaces through run prep (#10448) 2026-07-29 14:27:05 -07:00
index.ts fix: preserve runner recovery, warm sessions, and task outcomes (#13338) 2026-09-12 19:41:15 -05:00
instrumentation.test.ts fix(server): export manual OpenTelemetry spans (#10565) 2026-07-31 12:47:57 -07:00
instrumentation.ts fix(observability): pin the Sentry browser SDK and gate the optional Sentry server peer on the exact version (#12270) 2026-08-27 07:20:03 -07:00
log-redaction.ts Sync/master post pap1497 followups 2026 04 15 (#3779) 2026-04-15 21:13:56 -05:00
paths.ts feat(cli): add client commands and home-based local runtime defaults 2026-02-20 07:10:58 -06:00
peer-version-check.ts fix(observability): pin the Sentry browser SDK and gate the optional Sentry server peer on the exact version (#12270) 2026-08-27 07:20:03 -07:00
redaction.ts feat: add experimental native chat connectors (#13038) 2026-09-10 10:06:45 -05:00
runtime-api.ts Prefer loopback runtime API URL for local agents (#5102) 2026-06-20 14:03:21 -07:00
runtime-tools-token.test.ts feat(connections): add self-serve intent runtime (#12345) 2026-08-29 12:08:34 -05:00
runtime-tools-token.ts feat: use the responsible person's GitHub for shared agent operations (#13005) 2026-09-07 14:32:20 -05:00
sentry-dsn.ts feat(server): split the Sentry DSN into front-end and backend variables (#12678) 2026-09-01 11:02:04 -07:00
sentry.ts feat(server): split the Sentry DSN into front-end and backend variables (#12678) 2026-09-01 11:02:04 -07:00
server-info.ts fix(server): preserve source SHA without Git metadata (#9638) 2026-07-15 20:03:52 -05:00
shutdown.test.ts fix(db): reap idle pool connections, name the pool, and end it on shutdown (#12956) 2026-09-08 08:56:39 -07:00
shutdown.ts fix(db): reap idle pool connections, name the pool, and end it on shutdown (#12956) 2026-09-08 08:56:39 -07:00
startup-banner.ts fix(security): route paperclipai CLI guidance through safe npx form (CWE-78) (#11400) 2026-08-14 22:11:16 -07:00
startup-recovery-state.ts fix(runner): recover native sessions across restarts (#12845) 2026-09-04 15:03:53 -05:00
startup-refusals.ts fix(server): stop reporting expected managed-cloud transients to Sentry (#13323) 2026-09-12 11:15:43 -07:00
static-index-html.ts feat: allow operator UI snippets on Cloud instances (#13168) 2026-09-10 15:30:36 -07:00
static-ui-cache.ts fix(ui): keep the installed service worker fresh on parked tabs (#12198) 2026-08-25 16:12:02 -07:00
telemetry.ts fix: add periodic flush and graceful shutdown for server-side telemetry 2026-04-02 10:47:29 -05:00
ui-branding.ts Ensure worktree execution starts only after activation (#9374) 2026-07-10 16:11:26 -05:00
url-utils.test.ts fix(runtime): only rewrite base-URL port for loopback hosts (#10258) 2026-08-13 09:47:13 -07:00
url-utils.ts fix(runtime): only rewrite base-URL port for loopback hosts (#10258) 2026-08-13 09:47:13 -07:00
version.ts fix(server): stamp the real build version into images instead of the package.json placeholder (#10257) 2026-07-25 10:06:28 -07:00
vite-html-renderer.ts fix(runner): stabilize local paid E2E recovery (#12836) 2026-09-04 11:16:20 -05:00
worktree-config.ts feat(apps): consolidate connector management (#12684) 2026-09-01 14:55:35 -05:00
worktree-seed-manifest.ts feat(workspaces): sign the workspace login handoff and gate readiness (#11671) 2026-08-19 02:37:02 -05:00