paperclip/packages/adapter-utils/src/acpx-engine
Nicky Leach d1ba17eeca
fix(adapter-utils): fail fast when the sandbox control channel is lost mid-turn (#13158)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Adapter utilities run agent turns and report their results to the
control plane
> - A lost sandbox control channel can leave an agent turn without a
result
> - The host then waits for the full adapter timeout instead of
reporting the loss
> - This pull request adds a push loss signal and a bounded host wait
> - The benefit is a prompt failure terminal when the agent stops
answering

## Linked Issues or Issue Description

**What happened?**

A sandbox control channel loss during an Agent Client Protocol turn left
the host waiting for the four-hour adapter execution timeout.

**Expected behavior**

The host should detect the terminal channel loss, stop the turn, and
report a safe failure without waiting for the agent.

**Steps to reproduce**

1. Start an Agent Client Protocol turn through a sandbox adapter.
2. Close the duplex control channel while the turn remains active.
3. Observe the host response before the adapter timeout expires.

**Paperclip version or commit**

Test the pull request commit set at
`10b6bbc5525a79fd575298607dd5a25ae448fc8a`.

**Deployment mode**

The change applies to sandbox-backed adapter execution.

## What Changed

- Add `onLoss(listener)` to the duplex bridge handle.
- Register the loss listener at turn start and read losses latched
before turn start.
- Cancel the turn on loss and arm a 30-second host deadline.
- Close the stream locally when the deadline wins and create a host
terminal.
- Derive the public error from the closed `DuplexLossReason` enum.
- Add tests for loss order, cancellation, timeout, and safe error
output.

## Verification

- Run `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit`.
- Run `pnpm --filter @paperclipai/adapter-utils exec vitest run
src/acpx-engine/execute.test.ts -t "run-disposition seam"`.
- Confirm that the full pull request workflow passes.

## Risks

The new deadline changes a lost-channel path from a long wait to a
host-built failure after 30 seconds. Orderly completion keeps its
existing behavior. The deadline race against a pending `turn.result` has
no direct test.

## Model Used

OpenAI Codex, GPT-5, with tool use and code execution. The runtime does
not expose a more specific deployment version or context-window size.

## 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>
2026-09-10 15:37:05 -07:00
..
cli.ts
composed-run-characterization.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
constants.ts fix(adapter-utils): fail fast when the sandbox control channel is lost mid-turn (#13158) 2026-09-10 15:37:05 -07:00
execute-identity.test.ts feat(runner): bind ACPX profile boundary (#12387) 2026-08-30 12:37:13 -05:00
execute.test.ts fix(adapter-utils): fail fast when the sandbox control channel is lost mid-turn (#13158) 2026-09-10 15:37:05 -07:00
execute.ts fix(adapter-utils): fail fast when the sandbox control channel is lost mid-turn (#13158) 2026-09-10 15:37:05 -07:00
index.ts
local-process-control.test.ts fix: verify ACP Stop and preserve safe continuation (#13119) 2026-09-09 22:06:06 -05:00
local-process-control.ts fix: verify ACP Stop and preserve safe continuation (#13119) 2026-09-09 22:06:06 -05:00
operator-stop.test.ts fix: verify ACP Stop and preserve safe continuation (#13119) 2026-09-09 22:06:06 -05:00
remote-spawn-smoke.test.ts fix(adapters): persist ACPX process identity for hot restart (#9838) 2026-07-31 14:43:46 -07:00
run-contracts.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
run-contracts.ts fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187) 2026-08-25 14:32:14 -07:00
run-coordinator.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
run-coordinator.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
run-fault-matrix.test.ts fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187) 2026-08-25 14:32:14 -07:00
run-resource-ledger.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
run-resource-ledger.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
run-site-host.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
run-site-host.ts fix: verify ACP Stop and preserve safe continuation (#13119) 2026-09-09 22:06:06 -05:00
run-site-sandbox.test.ts fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187) 2026-08-25 14:32:14 -07:00
run-site-sandbox.ts fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187) 2026-08-25 14:32:14 -07:00
session-codec.ts fix: verify ACP Stop and preserve safe continuation (#13119) 2026-09-09 22:06:06 -05:00
session-reuse-store.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
session-reuse-store.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
settlement-characterization.test.ts fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187) 2026-08-25 14:32:14 -07:00
settlement-sequence.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
settlement-sequence.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
spawn-smoke.test.ts feat: add experimental native chat connectors (#13038) 2026-09-10 10:06:45 -05:00
startup-characterization.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
startup-timing.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
startup-timing.ts refactor: disambiguate the Telemetry and Observability data paths (#12128) 2026-08-24 16:42:33 -07:00
turn-characterization.test.ts test: add ACPX run lifecycle characterization baselines (#11461) 2026-08-15 21:36:59 -07:00
turn-sequence.test.ts refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576) 2026-08-17 22:02:16 -07:00
turn-sequence.ts fix: verify ACP Stop and preserve safe continuation (#13119) 2026-09-09 22:06:06 -05:00
ui.ts