## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The admitted Codex ACPX runtime can open and recover a verified session. > - It cannot yet accept a provider prompt through the narrow host port. > - Turn admission must bound durable identity and prompt payloads. > - Shutdown must cancel an active turn and release runtime resources in a bounded way. > - A cancellation timeout must not leave the runtime, command lease, or staged credentials alive indefinitely. > - This pull request adds the package-local turn lifecycle and its cleanup rules without production wiring. > - The benefit is one explicit and testable prompt boundary for the later harness driver. ## Linked Issues or Issue Description Refs #12402 **What would you like to improve?** The package-local ACPX host stops at session admission. A later driver needs to submit a prompt, consume typed ACP events, wait for the terminal result, cancel work, and close the session. Passing the full third-party runtime through the host would bypass the existing trust and cleanup boundary. **Why is this important?** Provider prompts can be large. Turn identifiers participate in durable correlation. Concurrent turns can make replay and cancellation ambiguous. Shutdown must also stop an active prompt before credentials and verified command resources are released. A provider that does not finish cancellation must not block all remaining cleanup indefinitely. **Suggested approach** Add a minimal turn interface to the admitted runtime port. Accept one prompt turn at a time. Bound the request identity and text before the runtime sees them. Map the call to ACPX prompt mode with the admitted session handle. Track the active turn and request cancellation before ordered runtime cleanup. Bound the cancellation wait. Continue runtime and command cleanup after that timeout. Release staged credentials only after the exact runtime close succeeds. **Additional context** This pull request builds on #12402. It does not attach semantic tools, normalize provider events, create a harness driver, start runnerd, register production execution, or change server, UI, or direct-adapter behavior. ## What Changed - Add a narrow ACPX turn input and result and event lifecycle to the admitted runtime port. - Map prompt turns to the exact persistent ACPX session handle. - Support abort signals without adding steering or attachments. - Reject empty, whitespace-normalized, or oversized request identities. - Reject prompt text larger than one MiB before third-party code executes. - Permit only one active turn per host. - Clear the active turn only after the canonical ACPX result settles. - Reject new turns as soon as shutdown starts. - Cancel an active turn before runtime, credential, and command cleanup. - Bound the cancellation wait to two seconds. - Continue runtime and command cleanup when turn cancellation fails or reaches its timeout. - Release staged credentials only after the exact runtime close succeeds. - Keep the cancellation handle and credential lease when runtime cleanup remains retryable. - Coalesce concurrent close calls and report all cleanup failures in one aggregate error. - Add focused host and adapter tests for turn mapping, bounds, concurrency, cancellation, timeout cleanup, credential retention, and late-turn rejection. ## Verification - Exact corrected head: `57e1edfcfc496bd9688c1ecf22f2d402c6bb2079`. - The pull request delta contains four files: - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts` - `packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.test.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.ts` - `packages/paperclip-runner/src/drivers/acpx/runtime-host.test.ts` - `git diff --check` passed for the exact corrected delta. - This delta does not change dependencies, `pnpm-lock.yaml`, workflows, migrations, server selection, UI behavior, or production runner wiring. - Full GitHub PR workflow passed in [run 33343457544](https://github.com/paperclipai/paperclip/actions/runs/33343457544): 28 successful checks, including runner verification/build, typecheck, all test shards, canary, and e2e; Storybook skipped by path as expected. - Greptile is 5/5 on the exact corrected head with no blocking failure and zero unresolved review threads. - Superagent Security, Snyk, contributor trust, and commitperclip passed on the exact corrected head. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this revision. ## Risks The primary risk is ambiguous concurrent execution. The host admits only one active turn and releases that slot from the canonical ACPX terminal result. Another risk is partial shutdown. The host requests cancellation first and waits for at most two seconds. It then attempts runtime and command cleanup even if cancellation fails or reaches the timeout. It releases staged credentials only after the exact runtime close succeeds. If runtime cleanup fails, the host keeps the cancellation handle and credentials for a later cleanup attempt. This pull request does not register the runtime for production use. ## Model Used OpenAI Codex with GPT-5 and repository tool use. ## 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 - [ ] 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 |
||
|---|---|---|
| .. | ||
| generated | ||
| protocol | ||
| runner | ||
| scripts | ||
| src | ||
| test | ||
| .gitignore | ||
| README.md | ||
| SEMANTIC_ACTIONS.md | ||
| package.json | ||
| rust-toolchain.toml | ||
| tsconfig.json | ||
| vitest.config.ts | ||
README.md
Paperclip Runner
This private workspace package contains the staged Paperclip Runner work.
The package currently exposes the language-neutral PRP v1 TypeScript contract, provider-neutral structured questions and responses, deterministic fixture validation/replay, structured-result normalization, and the session reducer oracle. It also contains a package-local Rust runner, scripted fake harness, bounded process supervisor, cross-language replay oracle, and durable PRP transport. The transport authenticates and encrypts loopback WebSocket sessions, persists an ACK-driven outbox and command journal, and reconnects with a short-lived lease. The Rust runner now includes a Codex-only app-server provider bridge with durable thread resume, cancellation, structured questions, and provider-neutral event normalization. The root surface now also exposes an authenticated durable PRP authority for server-side use. It stores only bootstrap and reconnect credential digests, validates immutable run identity on every connection and event, and persists commands and cumulative event ACK state across server restarts. The package also publishes the canonical semantic action declarations and their input and output schemas. Its package-local dispatcher projects only bound, run-authorized actions and emits redacted semantic receipts.
The first and only installed provider is Codex. Dynamic semantic tools remain
undiscoverable unless the hidden server coordinator projects one of the five
same-task read bindings for an already persisted native Codex run. Catalog
membership alone does not grant authority. The server can now create and start
a Codex-backed native run only through the default-off paperclip_runner
adapter. See
SEMANTIC_ACTIONS.md for the catalog boundary.
The package has two initial public surfaces:
@paperclipai/paperclip-runnercontains runtime contracts, validation, replay/reducer logic, the semantic catalog, the authorization dispatcher, and the Node-only durable server authority.@paperclipai/paperclip-runner/testingadds Node-only fixture loading and a provider-neutral semantic conformance kit for deterministic test adapters.
No SDK, browser, React, eval, live-console, lab, or provider-experiment entry
point is exported. The package remains private in this wave. The server route
at /api/runner/v1/connect/:runId has no authority until the hidden coordinator
registers an exact existing run binding. Fresh native starts are rejected
unless the instance enableNativeRunner flag is enabled. Existing direct
adapters keep their original execution path.
The package build compiles the release paperclip-runnerd executable and
stages it under dist/bin. The normal server build vendors that directory, so
an installed server does not depend on a separate system Rust installation or
a manually copied binary. pnpm-lock.yaml remains under the repository's
existing lockfile process.
Run the complete contract gate with:
pnpm --filter @paperclipai/paperclip-runner check:protocol
Run the Rust runner gate with:
pnpm --filter @paperclipai/paperclip-runner check:runner
This command checks Rust formatting, builds and tests the minimal workspace in
release mode, verifies bounded process cleanup, launches the real
paperclip-runnerd binary through the fake harness, and compares the Rust
conformance and replay summaries with the shared fixtures. The checked-in Cargo
lock and pinned Rust toolchain keep this verification reproducible.
Durability and failure semantics are documented in
runner/DURABLE_TRANSPORT.md. The fault suite
drops a connection before its event ACK, reconnects with the bound lease,
replays the same event, and proves the duplicated command effect ran once.
Codex launch, resume, cancellation, and normalization behavior is documented in
runner/CODEX_PROVIDER.md.
Use generate:protocol-manifest after a schema or fixture change,
generate:protocol-types after a schema change, and
generate:replay-goldens after an intentional reducer change. Commit generated
outputs with their sources; do not edit them by hand.
Use generate:semantic-action-catalog after changing a semantic action
declaration. Its checked-in JSON inventory must land with the source change.
The gate compiles every schema with AJV 2020-12, validates accepted fixtures, rejects unsupported required versions, checks generated TypeScript schema drift, runs the TypeScript contract tests, and compares reducer snapshots and parity summaries byte-for-byte with their checked-in golden files.