## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The package-local runner now has a durable PRP transport, but it cannot execute a real provider. > - The first provider must preserve PRP identities while using Codex native thread and turn identities. > - Recovery must resume the same Codex thread without starting a duplicate turn. > - Provider output must become bounded and provider-neutral before it crosses PRP. > - Semantic tools must remain unavailable until the catalog and authorization layers exist. > - This pull request adds the Codex provider bridge inside the runner package only. > - The benefit is a reviewable provider slice with no server or user-facing behavior change. ## Linked Issues or Issue Description **Subsystem affected** Cross-cutting. This pull request extends private provider infrastructure in `packages/paperclip-runner`. **Problem or motivation** The durable runner from #12100 has no production provider. It cannot start Codex app-server, map its events, cancel or steer a turn, deliver a structured question, or recover a native thread after process restart. **Proposed solution** Add a supervised Codex app-server transport and a normalized runner backend. Persist the Codex thread and active turn identities. Resume and inspect the exact thread after restart. Convert supported notifications into bounded PRP events. Keep the dynamic tool inventory empty. **Alternatives considered** The combined runner branch implements several providers, semantic tools, server coordination, and UI integration together. That change is too large for one review unit. Reusing the direct `codex_local` adapter would also couple this package layer to the existing server execution path. **Roadmap alignment** This work supports the governed tools and self-healing run direction in `ROADMAP.md`. It does not add a server endpoint, runtime adapter, rollout flag, or user-facing behavior. **Additional context** Refs #12100 and #11962. Pull request #12100 was squash-merged first. This branch starts at the resulting `master` commit. Its current delta is 16 files. ## What Changed - Added a Codex-only app-server process transport with bounded JSONL frames and buffered notifications. - Added strict provider descriptor validation for the Codex driver, working directory, launch arguments, model, instructions, and non-interactive approval policy. - Started new Codex threads with an empty dynamic tool inventory and the named workspace-only permission profile. - Added native turn start, steering, interruption, cancellation, thread reads, and structured question responses. - Added thread and active-turn binding checks for provider requests and notifications. - Added provider-neutral normalization for session, turn, item, plan, usage, tool execution, notice, and structured input events. - Bounded and redacted provider text and process output before durable persistence. - Added private atomic provider state for the descriptor, thread ID, account session ID, active turn ID, and unacknowledged normalized events. - Added exact-thread recovery through `thread/resume` and `thread/read`. Recovery does not issue another `turn/start` for an active turn. - Preserved active native turn identity across unexpected provider exit and reconciled it before later start, interrupt, or snapshot commands. - Added stable provider-event identities, per-event durable commit and acknowledgement, and a bounded fingerprint receipt journal that prevents duplicate delivery across outbox and provider-ack crash windows. - Extended the durable command executor with provider event polling and explicit process shutdown on stop, suspend, revocation, lease expiry, and runtime expiry. - Preserved completed shutdown behavior when the command result is replayed after a disconnect. - Added a fake Codex app-server and integration tests for response buffering, structured questions, interruption, provider exit, unacknowledged-event recovery, durable resume, and duplicate-turn prevention. - Added a focused `test:codex` package command for the provider integration suite. - Kept server code, UI code, other providers, semantic catalogs, tool authorization, and production runtime selection out of this pull request. ## Verification - `pnpm --filter @paperclipai/paperclip-runner check:all` passes. - TypeScript contract tests pass: 8 Node tests and 44 Vitest tests. - Rust tests pass: 43 unit tests, 5 Codex integration tests, 3 public durable-recovery tests, 2 local-runner tests, and 3 process-supervisor tests. - Rust conformance and replay parity checks pass against the shared PRP fixtures. - `cargo clippy --workspace --all-targets -- -A clippy::filter-map-bool-then -D warnings` passes. The narrow allow covers an unchanged replay implementation from the preceding contract pull request. - `pnpm -r typecheck` passes. - `pnpm build` passes. - `pnpm check:token-gates` passes. - `git diff --check` passes. - The delta against `master` is 16 files. The package lockfile is unchanged. The PR workflow generates its temporary lockfile artifact from the changed package manifest. - `pnpm test:run` completed locally with 4,690 passing tests, 19 skipped tests, and 26 failures in 8 unchanged server test files. The failures reproduce the established local macOS path-alias, listener, port-range, and workspace-runtime baseline. No changed-file test failed. Linux CI remains the repository handoff authority. - Browser and migration tests are not applicable because this pull request changes no server, UI, database, or migration file. - The full Linux PR workflow passes. One unchanged heartbeat recovery test timed out on the first pass and passed on the failed-only rerun; the aggregate `verify` gate is green. - Greptile is 5/5 on the final commit. All four review threads are resolved. ## Risks Production behavior is unchanged because no server code starts this provider. The main risks are a provider process escape, cross-thread event confusion, secret leakage, duplicated turns, duplicated or lost provider events, lost questions, and unsafe recovery. Process-group supervision, identity binding, private bounded state, redaction, durable command replay, retained event acknowledgements, bounded durable receipts, exact-thread reconciliation, and integration tests cover these risks. Semantic tools remain undiscoverable in this layer. I checked `ROADMAP.md`. This change is private provider infrastructure for planned control-plane work. It does not duplicate a shipped or public product surface. ## Model Used OpenAI Codex with GPT-5 was used. The exact serving model ID and context size were not exposed. The model used high reasoning, repository tools, GitHub tools, and local code execution. ## 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 --------- Co-authored-by: Paperclip <noreply@paperclip.ing> --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
Paperclip Runner
This private workspace package contains the staged Paperclip Runner work.
The package currently exposes only 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. No server code starts or invokes it. The package does not add a server adapter, semantic-tool authorization, or production Paperclip behavior.
The first and only installed provider is Codex. Dynamic semantic tools remain undiscoverable because the catalog and authorization layers have not landed.
The root export is intentionally narrow. The ./testing entry point and package
release boundary will arrive with the later package-boundary change.
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, verifies bounded process cleanup, exercises the fake local runner, and compares the Rust conformance and replay summaries with the shared fixtures.
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.
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.