Files
PaperClipAI/doc/acp-run-lifecycle.md
T
Nicky LeachandPaperclip b446ff59bf refactor(acpx-engine): coordinator-owned ACP run lifecycle with a typed resource ledger (#11576)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters run agent sessions through the ACPX engine
> - The ACPX engine handled one run attempt as a long implicit procedure
> - That shape made resource ownership, cleanup order, and failure
behavior hard to verify
> - This pull request gives the attempt a coordinator, a typed resource
ledger, separate run sites, and explicit turn and settlement sequences
> - The benefit is clear ownership, one cleanup path, safer session
reuse, and testable failure behavior

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The ACPX engine manages startup, turn execution, session reuse, and
cleanup inside one large run procedure.

**Current behavior**

The run procedure owns several resources through implicit control flow.
Cleanup and session reuse behavior depend on lane-specific branches and
error paths.

**Proposed behavior**

The coordinator owns the run attempt. A typed ledger records six
resources and their states. Host and sandbox run sites own lane-specific
acquisition. Turn and settlement sequences expose typed outcomes. The
engine emits allowlisted phase telemetry.

**Reason and benefit**

Explicit ownership makes cleanup and failure behavior easier to inspect.
The fault matrix and characterization tests protect the external result
while the refactor reduces hidden control flow.

**Breaking changes**

None to the public adapter contract. The host warm-save path now closes
and relaunches the runtime because a transferred runtime could retain a
run-scoped credential. A cold session-handshake failure now closes the
created runtime.

**Additional context**

This pull request contains the ACPX engine lifecycle refactor, its
tests, and the lifecycle document.

## What Changed

- Add a run coordinator for startup, turn execution, settlement, and
result reproduction.
- Add a typed resource ledger with open, sealed, and consumed states.
- Add host and sandbox run sites for lane-specific resource acquisition.
- Replace separate runtime maps with a generic session reuse store.
- Split session fingerprint identity from the outer session key.
- Add typed turn and settlement sequences with one cleanup owner.
- Add a closed allowlist for phase telemetry.
- Add characterization tests and a 17-case fault matrix.
- Add `doc/acp-run-lifecycle.md`.

## Verification

- `npx vitest run packages/adapter-utils/src/acpx-engine/` passes 18
files and 286 tests at the submitted commit.
- `pnpm --filter @paperclipai/adapter-utils typecheck` reports 0 errors
at the submitted commit.
- Run the full pull request checks after GitHub starts CI.
- Run Greptile review after the pull request opens.

## Risks

- The refactor changes internal control flow across the ACPX engine.
- Host warm-save behavior now closes and relaunches the runtime.
- Settlement changes the handling of a cold session-handshake failure
from a leak to a close.
- The characterization baselines and fault matrix reduce the risk of an
external behavior change.

> Paperclip is the open source app people use to manage AI agents for
work
> The adapter layer runs agent sessions through the ACPX engine
> The engine needs explicit lifecycle ownership for reliable cleanup
> This pull request adds coordinator-owned phases and a typed resource
ledger
> The result makes lifecycle behavior easier to test and review

## Model Used

OpenAI GPT-5 Codex. Exact model ID: GPT-5. The model used tool
execution, repository inspection, and code review support. The
implementation author supplied the submitted code.

## 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-08-17 22:02:16 -07:00

5.0 KiB

ACP run lifecycle

This document describes how one ACP agent run starts, runs its turn, and releases its resources. It covers the run coordinator, the six run resources, the settlement order, the server-owned staging lease, and the known limitations.

The run coordinator

One run() coordinator owns one attempt. It sequences four steps in a fixed order:

  1. Startup. Bring up the runtime and establish the session.
  2. Turn. Run the agent turn against the ready runtime.
  3. Settlement. Release every resource the run acquired.
  4. Result reproduction. Return the external result to the caller.

The coordinator holds the routing table as data. It reads the startup outcome and routes on it:

  • A build failure or a partial-bridge failure throws from startup. The coordinator replays the startup-rollback entries and rethrows the original error.
  • A runtime-create, handshake, missing-handle, or configuration failure produces a settle result. The coordinator settles the resources, then reproduces the error result.
  • Every other startup outcome produces a ready result. The coordinator runs the turn, settles the resources, then reproduces the turn result.

The coordinator has no catch around the turn: the turn never rejects and returns a typed completion. The coordinator reproduces the external result AFTER settlement, so a caller never observes a result before the run releases its resources.

The six run resources

A run resource ledger holds the resources between acquisition and settlement. The ledger is the single owner. The closed set of run resources is:

  • acp_runtime — the composite of the runtime, the session handle, and the child process. runtime.close() is the one release boundary for all three.
  • staged_runtime — the workspace and the runtime staged into the sandbox, plus the one-time host-side cleanup of the staged temporary files.
  • control_bridge — the control-plane callback bridge.
  • agent_bridge — the agent process-session bridge.
  • managed_home — the per-run managed-home copy-back hook.
  • staging_lease — the per-session staging lease.

The host lane acquires only acp_runtime. The sandbox lane also acquires the staging and transport resources. Each resource enters the ledger the moment it exists, so the settlement always closes it, even on an early failure.

The settlement order

The settlement sequence is the one live cleanup owner for every settled path. It claims the ledger once, makes the pure reuse decision, then runs the ordered steps:

  1. end_session — close every runtime the reuse decision did not transfer, and drop the warm entry when it closes.
  2. settle_reuse — perform the decision. A save transfers the reuse candidate to the site store; every other case discards it.
  3. stop_transport — stop both bridges in one settled batch.
  4. sync_back — run the site sync-back (the managed-home copy-back).
  5. release_staging_lease — release the staging lease last (see below).

An error policy governs every step: a step records its error, and the later steps still run. Every step is a no-op on an empty resource slot.

The reuse decision is pure and runs before any close. A save is eligible only when a candidate exists, the settlement cause permits a save, and no run-scoped credential that the candidate would carry into the store remains valid.

The server-owned staging lease outer context

The staging lease is a per-session lease. Only one run of a session may stage into the same remote workspace at a time. A second run of the same session waits on the lease until the first run releases it.

The lease releases as the run's final act, after the coordinator settles every other resource AND reproduces the result. This ordering keeps a same-session second run blocked on the lease until the first run fully returns, so the second run never re-stages into a workspace the first run still uses. The release runs in a finally, so an earlier teardown fault never strands the lease.

Per-phase telemetry

The run emits one telemetry event per named lifecycle phase. Each event carries only the phase name, the wall-time duration, and the outcome (ok or failed). The phase name is one member of a closed allowlist. An event never carries a command, an argument, a path, an environment value, or a raw identifier. A telemetry failure never fails the run.

Known limitations and deferred work

  • Host-lane runtime reuse is disabled. A run-minted API key is a stateless token that the control plane never revokes on run end. A warm host runtime would carry a still-valid credential into the next run. The host lane therefore closes and relaunches on every run, rather than keeping the runtime warm, until a run-scoped credential rebind protocol exists.
  • The sandbox staged-files reuse stays enabled. Its reuse payload carries no credential, so a compatible resume reuses the already-staged runtime.
  • The per-phase telemetry is observability-only. It records the duration and the outcome of each phase; it does not change run control flow.