Files
PaperClipAI/doc/architecture/runner-pi-capabilities.md
Dotta 73eee2c0d6 docs: Pi core production readiness evidence (5/5) (#14956)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The experimental Runner owns provider processes and durable
sessions.
> - Pi needs working task execution and human controls.
> - The five-PR stack must preserve changes already on master.
> - The runtime implementation has merged in #14921; this layer carries
the next documentation changes.
> - This PR belongs to native GitHub stack #15602, ending at #14956.

## Linked Issues or Issue Description

Refs #14436, #14631, #14743 and #14956.

Ship Pi 1.0 through the experimental Paperclip Runner. The five PRs are
#14921, #14922, #14923, #14924 and #14956. The user authorized the
complete merge after checks pass. Existing `pi_local` execution is
unchanged. Accounting and wider provider/platform qualification remain
deferred.

## What Changed

- Record the seven source-bound Pi core passes and retained
failed-attempt provenance.
- Document agent-file artifacts, warm instruction-root recovery, final
task replies, and installed Runner verification.

## Verification

- Full local `pnpm -r typecheck` passes, including Runner Rust, server
and UI. Focused integration checks pass: 194 Runner
admission/environment tests, 63 profile/credential tests with one
expected skip, 152 Dot/UI configuration tests, and Pi transcript/notice
tests.
- Full local `pnpm build` passes on the final source.
- Fresh final-source checks pass: all 698 Rust workspace tests (32
binaries), 156 credential/profile/controller tests with one expected
skip, Runner TypeScript typecheck, and 20 package/setup/sandbox tests.
- The profile-21 Pi materializer passes on the native host with the
official pinned Node 24.21.0 and its npm. It verifies all 150 locked
packages, the patched dependency and the exact closure. Setup/package
bundle tests and UI token gates pass.
- The old hashes were reproduced for all three supported targets before
calculating the patched graph. New closure hashes are darwin-arm64
`282022db10150c6632b3444df421342e7d534bdf5d5fb1097a2e79d0625a2bcf`,
darwin-x64
`64e251e19009f755c0b04f73ce2138246faab71a961b0f13d75ebfcc34bef12e`, and
linux-x64
`713b1fdff42fb56a1518bdc084f181d70bee8ebadc3e4b1d76321ed9108c8410`.
Independent native platform execution is separate from graph identity
reproduction.
- Historical cloud qualification remains unchanged: all seven core cases
pass on shipping source `10dc43c9ec65d88c2f782d62afb296d09494f215`,
harness `1a4408a48cfb5a1f094a311141c257c92cd7a893`, image
`sha256:5b3a775b383591bda1b0c1889e509acc70ce7f37c53f09733c81d59037f02280`,
and accepted Sonnet 4.6/low fixture. All 215 canonical files and all
seven cleanup checks pass independent verification. These are profile-19
results and are not relabeled as fresh profile-22 runs.
- Current Pi digest:
`sha256:e92078bee3c23bec4100aa589013a44613d054cd686826534025d8019e9f39a9`.
[The readiness
plan](https://github.com/paperclipai/paperclip/blob/codex/pi-production-readiness/doc/plans/2026-10-02-pi-production-readiness.md)
preserves campaign and failed-attempt provenance.
- Merge only after every PR's current-head CI and fresh review pass.
Linux CI covers the full suites, build and browser tests. The local
embedded Postgres API-authority suite cannot start on this macOS/Node 26
host, so Linux CI must confirm that suite.

### Fresh profile-22 core qualification — 2026-10-08

All seven accepted core cases pass canonically on Pi profile 22, with
`openrouter/anthropic/claude-sonnet-4.6` and native-confirmed low
thinking. This model is a fixture; production accepts the caller's
explicit Pi provider/model.

Runtime/install source: `3241a992f2a7703e59e97ed0fd3e5d6405de4401`.
Frozen accepted harness: `1a4408a48cfb5a1f094a311141c257c92cd7a893`.
Immutable cloud image:
`ghcr.io/paperclipai/paperclip-daytona-runner@sha256:506f22db7edd78f37c0c40bec1cc084af1850455026dbf467194bfbb8fcef141`.
Pi digest:
`sha256:e92078bee3c23bec4100aa589013a44613d054cd686826534025d8019e9f39a9`.

[Hosted Linux image and clean-install
verification](https://github.com/paperclipai/paperclip/actions/runs/37868328023)
passes, including all 20 source-bound archives, normal CLI/Pi setup,
companion import and the production pack reader. This exact installation
source includes the latest master integration and the corrected Pi warm
instruction-root fence. Full local typecheck/build and current-head
hosted CI verify the final stack. All 13 focused real-root regressions
pass. The full local executor suite passed 662 tests; 15 database tests
could not start the Mac embedded PostgreSQL service. Hosted Linux CI
passes the full required verification and E2E checks. These fresh
results keep their own source identity; profile-19 results remain
historical.

| Core path | Canonical campaign | Retained archive SHA-256 |
| --- | --- | --- |
| File edit, validation, download and Done |
`pi-core22-replyfix-0-1791511228` | 23 files;
`a473e8603a3dd4737863291f8d3d1e392391f0b16d433c3e0e0e9d8baf7a97b0` |
| Pending question and controller restart |
`pi-core22-replyfix-1-1791511376` | 33 files;
`6b829c4eb74e1f32a89c692a4ae7130dbfc1c6d3cf13915effe2103d9e242c8e` |
| Three-turn session/process/workspace continuity |
`pi-core22-replyfix-2-1791511587` | 23 files;
`7a87021f8f9a3fdd3c58bb4467f8d82c635e3ea4795d6e75f144d9aa14818df8` |
| Four typed questions and browser reconnects |
`pi-core22-replyfix-3-1791511881` | 42 files;
`9e31755252be1f4f9cb0626c984c142d4d1ae5f5bee3a7af08444db8d12c280a` |
| Plan approval and completion | `pi-core22-replyfix-4-1791512031` | 22
files;
`a0383ce1aab38e7b5a25ce0e9dd3bebea5c037ebd96ae6b29dae19015da2ae2c` |
| Same-turn steering and permission denial |
`pi-core22-replyfix-5-1791512261` | 39 files;
`c929b8c7070f0b66aedc17e65ca46e6beab1e363926ac9f7e2a75fb250f05949` |
| Stop during pending permission | `pi-core22-replyfix-6-1791512390` |
33 files;
`7f0a58ae0f4d5bfc76149435f4e322537089c5bd16e7ffe9b5ad71f10a621a07` |

All 215 canonical files (28714587 bytes) are independently
hash-verified. All seven cleanup grades pass, with no owned runtime
process or temporary root after each case. Automatic retries are zero.
The owned cloud host stopped normally after retention. The prior
profile-22 warm attempt remains failed and separately retained: archive
SHA-256
`1e54eba5ec72b50cee1534b23d1d1d4f21a090006b8a64501ba70db972abfde5`. Its
original canonical classification is preserved. Diagnosis reproduced a
product bug comparing an agent-files root against an unset
checkpoint-only field. The fix stores the admitted physical root
separately from the adopted per-run collection capability. The real-root
regression fails before the fix and passes afterward, including
rejection of a changed physical root. Fixture, grader, model and all
seven accepted case IDs are unchanged; this fresh campaign tests
final-reply publication after file registration first. The intermediate
restart attempt also remains failed and retained: archive SHA-256
`5dcaefdf1d17cf4cd54fd4cf810f45e736667392339b8ce7caf08bb4e225277f`. Its
original canonical classification is preserved. Pi resumed, wrote the
verified answer and completed its task; exact runner suspension was
proven, but idle stop consumed about 5.2s and left under 3s for the
drain acknowledgement. The Pi-only default shutdown grace is now 15s,
preserving a full 5s drain round trip and a finite suspension reserve.
Explicit caller deadlines, other provider defaults, literal drain
receipts and exact suspension identity checks remain unchanged. The
timing regression fails before this correction and passes afterward; all
18 focused settlement tests and Runner typecheck pass. The final-source
file attempt is also preserved as failed (`candidate_failure`), archive
SHA-256
`db6767b6773ea618997927ac77bdb005a5ac81492c7b9c0ffbc900449f829bc9`.
Native edit, validation, exact downloadable artifact and Done/succeeded
all passed, and the exact final reply was durably recorded. A workspace
recovery owner completed before the live heartbeat reached presentation,
leaving that reply absent from task chat. Recovery now materializes only
a completed final reply from the accepted turn of an ordinary internal
Done task, preserving issue/run/contract binding, suppression,
external-chat authorization and same-run deduplication. The database
regression covers the generated file-preparation receipt, suppression,
unapproved external continuation and replay. Server typecheck and all 49
response-selection tests pass; hosted Linux verifies the database
regression because embedded PostgreSQL cannot start on this Mac.

The delayed-final-answer database regression passes on [the final
root-source Linux server
shard](https://github.com/paperclipai/paperclip/actions/runs/37868262553/job/113628594152),
alongside 1,108 passing tests. The first root Runner shard had one
unchanged durable-resume test exceed its 5-second timeout; the identical
top-source shard and the isolated exact test passed. One rerun of that
failed job and its required aggregate passed without source or test
changes. The original failed job log and the single-rerun receipt remain
retained.

### October 9 merge verification

Current merge head: `e77273aa0fce5991a5b5dd193734fd6b0a6542d3`. All
current-head checks pass, including `ci / verify` and `ci / e2e`;
exact-head Greptile review is 5/5 with no unresolved threads. Current
master conflicts are resolved. The user authorized the maintainer
override of the code-owner review gate after these checks. The seven
retained live core cases remain bound to source
`3241a992f2a7703e59e97ed0fd3e5d6405de4401` and its recorded cloud image.

## Risks

- The security correction changes the dependency closure and profile
identity. Old sessions must reopen on the new profile. Exact identities
and credential bindings fail closed.
- The runner remains experimental and requires explicit selection.
Legacy Pi Local is unchanged. Caller model IDs pass through; the E2E
model is a fixture.
- Accounting and the broad platform/provider matrix remain deferred.
This merge does not publish a release or deploy a service.

## Model Used

OpenAI GPT-6 through Codex assisted with reasoning, repository
inspection, editing and tool use. The exact serving ID and context
window are not exposed in this session. Final live qualification uses Pi
1.0.0 with `openrouter/anthropic/claude-sonnet-4.6` and native-confirmed
low thinking.

## 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
2026-10-09 11:15:09 -05:00

87 KiB
Raw Permalink Blame History

Pi rich ACP runtime

Current integration — 2026-10-08

The experimental Runner admits Pi profile 22 (sha256:e92078bee3c23bec4100aa589013a44613d054cd686826534025d8019e9f39a9) and Cursor profile 15. Copilot remains pending at profile 17. Legacy pi_local is unchanged. Pi accepts any explicit caller-selected provider/model ID and requires native acknowledgement; qualification models are examples, not an allowlist or a fallback.

The requested task execution and human-control paths have seven passing cloud cases on profile 19 with the accepted Sonnet 4.6/low fixture. Profile 22 retains that wrapper, helper and extension, incorporates master's environment changes, patches brace-expansion to the official 5.0.12 payload, and excludes general AWS IAM credentials from Pi's environment. Bedrock's provider-scoped bearer key is supported. Those paid results retain their original profile-19 identity; current integration is verified separately by source, package and CI checks. Accounting and the wider platform/provider matrix remain deferred. See the readiness plan for the exact source/image evidence and merge status.

All dated checkpoints below describe historical qualification attempts. Their failures and profile numbers are retained; they are not current release gates.

User-selected models (2026-10-06)

Native Pi accepts any explicit provider/model ID. The settings builder, server, release profile, and Rust runner do not restrict selection to a qualification model. Pi must acknowledge the exact selection before a prompt and on recovery; unavailable models fail clearly without selecting a substitute. Runtime package, version, command, permission, and process-ownership checks remain enforced.

Bind the selected provider's credentials in the agent environment, for example OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENROUTER_API_KEY. Custom models use PAPERCLIP_PI_PROVIDERS, an explicit JSON object in Pi's models.json providers format. The runner writes it into the private Pi home, forwards explicitly bound credential references, and includes its digest in recovery identity. Credential commands and control-plane credential references are rejected. General AWS IAM keys are excluded; Bedrock uses AWS_BEARER_TOKEN_BEDROCK. Choose a thinking level supported by the selected model (off for a model without reasoning).

The DeepSeek model IDs throughout the historical qualification results below identify those attempts; they are not a product allowlist. Those results do not qualify this merge or additional models.

Historical Pi 1.0 candidate (2026-10-02, profile v13)

Pi remains pinned to @earendil-works/pi-coding-agent@1.0.0, with pi-acp@0.0.33, ACPX 0.13.1, and Node 24.21.0. Profile 13 adds explicit reasoning-mode selection and rejects previous profile identities. It is a new qualification candidate; profile-12 results below remain historical evidence.

Pi's new field also changes four shared files covered by Copilot's source identity. The subsequent live callback snapshot changes the shared sidecar again, so Copilot now uses still-unqualified profile v14 without changing its executable or model. Pi's profile-13 identity and native closure remain unchanged. Final artifacts must bind the corrected source; the initial ARM startup and 61 contract passes alone do not establish production readiness.

The normal Pi configuration records piThinkingLevel as off, low, high, or max. New configurations and qualification cases explicitly select low. The runner binds that setting to the session identity and requires native confirmation of the effective level before sending the prompt, including after session restoration. An unsupported level, absent acknowledgement, or effective level different from the requested value must fail admission. Changing the level requires a new compatible session; a warm session cannot silently retain its previous setting.

The wrapper obtains available levels from Pi's native get_available_thinking_levels RPC, exposes them through ACP session modes and the thought_level configuration option, and confirms changes with native get_state. This avoids advertising the static minimal, medium, or xhigh aliases when the selected model does not support them. For the pinned DeepSeek model, Pi 1.0 supports off, low, high, and max. Pi's implicit medium default resolves to high; Pi 0.84.2 also resolved that default to high, so this is a configuration gap rather than evidence of a new Pi 1.0 default.

The provider-free wire proof records actual Pi 1.0 request bodies changing from high to low through ACP, truthful max restoration, blocked non-loopback connections, and owned-process retirement. Synthetic responses establish propagation, not paid qualification.

The paid profile-12 hello passed in the actual installed application. Its first question continuation failed at the unchanged 120-second native deadline after 1,019 reasoning deltas and no emitted tool call or question. The required tool was present with its exact schema. This establishes model activity without the required interaction; it does not prove the reasoning setting caused the timeout. The test remains failed. Profile-13 deterministic, local paid, Runner, native control, and Daytona results must be established independently.

Capability Native / ACP surface Paperclip surface Remaining boundary
Supported thinking levels get_available_thinking_levels; ACP available session modes and thought_level choices Pi reasoning-level configuration Model selection is explicit and unrestricted; historical qualification used the recorded model and level.
Set and verify thinking level Native set_thinking_level, then get_state; ACP session/set_mode / config option Saved agent setting, typed runner input, effective-mode admission Live setting changes during an active turn are not exposed; a new compatible session is required.
Recover selected level Native restored state plus explicit effective-level verification Mode-bound durable session identity Old profiles and missing or mismatched mode identity cannot reuse a warm session.
Provider notice severity and pricing provenance paperclip/pi_notice and canonical provider.notice.recorded Retained run event, usage metadata, and safe summary with severity in the activity row Summary/severity rendering has deterministic coverage; paid visual verification of the rebuilt UI remains pending. Pricing estimates remain distinct from provider billing receipts.

Historical profile-13 qualification checkpoint (2026-10-02)

The installed candidate from source eac50643213d0902a93a5384bae2f1d6c065c9f2 uses Pi 1.0.0, the explicit OpenRouter DeepSeek model above, and verified low reasoning. Paid local Product E2E passes cover hello, semantic question/answer continuation, all four native question forms, and human permission denial with no file side effect. The paid extended Runner get-task-context case also passes through the packaged runner against its authenticated, seeded test control plane. Runner protocol evidence does not qualify the Product UI.

Three local attempts remain failed: file-edit validation, pending-input controller restart, and three-turn warm continuation. The first two exposed assertion gaps: streamed command output supplies the exit receipt, and a pre-start submission may precede assignment of the native turn ID. Narrow fixture repairs have positive and negative coverage; neither failed attempt has been regraded and both require fresh live runs.

The warm attempt completed its first turn and edited files on its second, but its final semantic tool stayed pending until the existing deadline. OpenRouter metadata joins the exact native session and records the final response as cancelled with no finish reason. This supports an unfinished upstream response at cancellation; it does not establish why the response stopped progressing. A real pinned SDK/wrapper replay proves both restored-session completion with the new agent home and completion contract, and safe cancellation when complete tool JSON arrives without the provider's stream finish marker. The latter executes no semantic mutation. No timeout or runtime policy was changed to make that replay pass.

Fresh builds must incorporate the subsequent launch, UI, and fixture fixes. macOS Intel startup, the remaining local and Runner cases, Linux/Daytona, and final source-wide checks remain qualification gates. The provider remains unqualified until that evidence is complete. API-key usage observations cover the capped qualification campaign; native pricing estimates are not bills.

Historical Pi 1.0 profile-v12 checkpoint (2026-10-02)

The candidate now pins @earendil-works/pi-coding-agent@1.0.0 with pi-acp@0.0.33, ACPX 0.13.1, and portable Node 24.21.0. Pi v11 and older sessions must reopen. Cursor v10, Copilot v12, and legacy adapters are unchanged. This is a new runtime candidate: historical Pi 0.84.2 passes do not qualify it. Local Product, Runner protocol, and Daytona paid qualification remain pending.

The official release points to commit a13d35a742c6ef8462812a28fbe1d8c8b7431c32. The npm archive is verified against published SHA-512 integrity /FtbxoSQU/mEv1QnichJjRjqteqaIaMWxmhB4G367+MwZfX7/DI5B9YAg5lqbN7nztFskBEtUSZ+FlmMBECtMw== and has SHA-256 638ed3abbe54ef70cbf8673ae4bc531e791613756aac04644cfcdcc4af0fafaf. The isolated npm lock preserves the complete upstream shrinkwrap, supplementing seven Pi-family entries' omitted integrities from their exact npm 1.0.0 records. Upstream now pins Undici 8.10.2 itself; the previous 8.9.0 replacement is removed.

Profile v11's first local hello failed on its first streamed update: Pi 1 RPC removes message and partial from deltas, while the wrapper required the old shape. The run stopped and the task became blocked; this was a runtime compatibility failure, not a successful hello. V12 binds deltas to the original message occurrence, tracks indexed tool fragments, and checks completed text, thinking, tool identity, and arguments against native final receipts. Real Pi 1 RPC/owned-extension tests reproduce the failure and pass the repaired local-only get-context → finish path, interleaved tools, and a sanitized provider error. These synthetic loopback responses establish compatibility, not paid qualification. Pi may also send a native final message without streamed blocks. That receipt is preserved without inventing deltas; only observed completed stream blocks are checked against its indexed content. Error or aborted receipts may retire incomplete blocks, but cannot contradict blocks already completed.

Runtime failures now emit bounded known reasons before prompt rejection. Raw exception bodies, credentials, paths, and unknown text stay withheld. Actual provider token usage still comes from native completed receipts; fixture usage is not live billing evidence. New wrapper/helper closure pins and Rust admission constants require fresh platform packs and daemons. Historical v11 artifacts must not be relabeled as v12.

Compatibility changes preserve the existing rich runtime surface:

  • Native steering and follow-up acknowledgements now carry disposition. Only queued is accepted as delivery; handled, missing, or malformed dispositions fail visibly. Settlement still waits for agent_settled.
  • Pi defaults streaming cache warming to enabled. The owned extension overrides every cache_warming_decision with stop; no background model refresh is authorized by an active or completed Runner turn.
  • Pi's new built-in extensions are disabled by the existing --no-extensions. The explicitly loaded Paperclip extension still supplies assigned MCP tools, native questions, permission decisions, instructions, and registered agent files.
  • Structural system message boundaries carry prompt/tool declaration changes. They pass through without assistant IDs or final-answer authority; malformed structural frames and overlap with an active assistant still fail closed.
  • Pi's transcript-context API replaces the old provider context.tools view. Provider-free SDK tests read current declarations through Pi's canonical helper; production RPC parsing keeps message/tool boundaries and usage intact.

The upstream changelog and RPC interface add capabilities which must not be confused with wrapper support:

Priority Native Pi 1 capability Runner status and reason
P1 Codemode, nested calls (parentToolCallId, nestedCalls), deferred tool search, exposure/annotations/output schema Available upstream; built-in extensions remain disabled until nested provenance, permission checks, and output projection are qualified. Assigned semantic MCP tools retain direct exposure.
P1 Native MCP OAuth, provider-auth HTTP MCP, OAuth issuer/scope hardening Available upstream; arbitrary MCP/auth discovery is outside the closed assigned bridge. Paperclip owns credential and company scope.
P1 Image generation and classifier calls through ModelRuntime/codemode Available upstream; not exposed because separate model calls need budget attribution and artifact admission. Text/image tool-result transport remains supported.
P1 clear_queue, per-input queued/handled disposition Disposition is checked now. Queue clearing still needs a durable Runner cancellation contract; Stop continues to abort the owned active process/turn.
P2 Append-only context edits, actionable turn_end/agent_before_settle, context_with_system Available upstream; only existing observation hooks are installed. Host-directed edits need durable recovery semantics before exposure.
P2 Provider stream hooks, virtual models, per-model compaction/image sizing Available upstream; no arbitrary provider extensions or virtual routing are admitted. Native compaction and existing model configuration remain supported.
P2 UI prompt lifecycle events and richer startup/fullscreen TUI Native UI exists; Runner uses RPC and its existing question/wait states. No terminal TUI is advertised.
P2 Fork/clone/history export Native RPC capabilities remain available upstream; durable branch lineage and contained exported-artifact handling remain required before Runner controls expose them.

Pi's published CLI mode union is text | json | rpc; no native ACP mode is present in this release. The reviewed pi-acp wrapper remains necessary.

Explicit Linux companion setup for a Mac controller

A Mac controller needs independently verified Linux runner bytes for Daytona. Its host Pi installation is not a Linux provider pack. The operator imports a release companion once, before launching agents:

paperclipai runtime import-remote /path/to/release/linux-x64 --sha256 MANIFEST_SHA256

Obtain MANIFEST_SHA256 from the trusted release channel, separately from the copied directory. The directory contains companion.json, bin/paperclip-runnerd, and the complete provider-pack/. Import verifies the installed server's exact build commit, qualified Pi profile, Linux x64 ELF, manifest digest, and every file, mode, directory and contained symbolic link. External hardlinks, escaping links, extra or modified files, and unsafe modes are rejected. This command performs no network requests or model calls and does not run the Linux executable on the Mac.

The destination is the private remote-companions/linux-x64 directory beneath the actual installed @paperclipai/server package. It must be writable by the operator, outside the task workspace, and protected with the same host access controls as the server installation. It is not an agent workspace or a remote image's self-reported authority. An existing different or damaged installation is never replaced automatically. Stop all runs before an operator removes or upgrades that cache. Verification and copying use asynchronous 1 MiB chunks, yield between chunks, and enforce the same full inventory and ten-minute bound. Directory entries must retain owner read/write/search permissions so failed imports can drain their owned cleanup. SIGINT/SIGTERM are deferred through owned filesystem phases and drain cleanup; an uncatchable kill or host failure leaves the import unadmitted until the operator resolves its retained lock or incomplete directory. Do not move the cache into a task workspace to work around permissions.

Normal remote Pi resolves this authority without binary or pack environment overrides. The controller re-verifies its complete inventory and uses the exact Linux daemon identity. Existing remote verification compares image bytes against that local authority; a mismatch takes the existing verified upload path. Controller restart and warm-session recovery retain the original Runner artifact identity checks. Cursor, Copilot and explicit operator overrides keep their existing admission rules.

For release maintainers, assemble the Linux daemon and default provider pack for the same final commit as the public server/CLI packages. A reused daemon requires complete native source/config/protocol input equality and retains its original compiler/build provenance; the manifest does not claim recompilation. In a fresh release directory place those outputs at bin/paperclip-runnerd and provider-pack/, preserving the pack's relative links and modes. Then run the source-owned manifest generator after building the matching server:

node scripts/create-runner-remote-companion.mjs /path/to/release/linux-x64 FINAL_SOURCE_SHA

Publish the complete companion directory (or distribute it through the normal trusted release channel) together with the printed manifest SHA256 and the source/profile/platform provenance. The import command accepts an already extracted directory, not an archive or URL. The release companion must remain available with that release; a short-lived qualification artifact is not a release distribution. No release publication is implied by the tests here.

Build/publish the Daytona image from those same daemon/pack outputs and configure its immutable OCI digest through the ordinary Daytona environment image field. The image digest and companion manifest are output metadata, not new source constants, so publication does not require another source commit. The final live proof must use the installed public CLI, this import command, and ordinary image configuration without E2E remote binary/provider-pack overrides. That installed and paid proof remains pending.

Historical v10 qualification checkpoint (2026-09-30): Pi profile v10 remains unqualified. The capped-key/login prerequisite remains blocked. Native USD is unknown. The optional private budget helper is not integrated; Cursor's account-cycle cap does not establish Pi's provider spending bound. V10 keeps the native wrapper and closures unchanged, binds the shared ACPX patch under a new digest, and rejects v9 sessions. Fresh exact-runtime admission and final controller verification remain pending.

Historical v9 checkpoint (2026-09-30): Pi profile v9 remains unqualified. Current runtime source is 5b8e4454ef0bf12d0bb068c2e41d8c9df9356a1c; controller/Product harness source is 40064d28522de25fea85c1297f35b41bb8a8897a. Runtime builds for macOS ARM64/x64 and Linux x64 are complete. No paid profile-v9 pass is claimed. A credential with a verifiable spend limit is still needed for the remaining paid qualification. The optional transport-budget candidate is frozen on a separate branch and is not integrated or a live spending guarantee. See the comparative capability report for current qualification gates and the field audit. The dated observations below retain their original profile identities.

Historical implementation candidate, 2026-09-29: profile version 8 repairs native assistant-message attribution. Real SDK message_start and message_end boundaries, including empty messages, carry occurrence IDs through ACPX, the sidecar and both terminal reducers. Tool-use, error and aborted messages remain progress but cannot become a final answer. Missing or conflicting boundaries fail closed. Loaded history has a separate display-only identity. Retry, compaction, extension and command notices retain bounded, redacted severity and metadata on paperclip/pi_notice; they are never assistant final content. The v8 declaration also pins the shared ACPX parser and Pi host projections. Previous sessions must be reopened. No paid profile-v8 qualification has run.

The retained profile-v7 campaign passed native questions (15/15), then failed question continuation (5/6): the model emitted the exact final marker, but the old terminal reducer combined it with pre-tool narration. That failed Product result remains a failure; the remaining five cells were not launched. The v8 credential-free regressions reproduce this boundary through the actual pinned SDK (fresh, warm and loaded sessions), patched wrapper, ACPX transport, sidecar, TypeScript driver and Rust reducer. This is deterministic repair evidence, not a replacement for the failed paid journey.

Historical profile version 7 repairs MCP tool-name admission and native question labels. MCP names containing colons or periods, or exceeding model name limits, receive deterministic collision-checked aliases of at most 64 characters; authenticated calls retain the exact original name. Titles and select labels admit at most 1,000 UTF-16 code units, matching the canonical question contract. Invalid owned arguments fail before a UI promise; unsupported external UI requests emit an explicit error notice and stop the session. The editor draft requires the shared initialText normalization and editable UI roundtrip. Blank initial drafts are valid, but accepted empty or whitespace-only input/editor answers are not currently representable: the canonical required-text form prevents submission with a required-answer message, and its response validator rejects blank text. Making Pi fields optional alone would still drop those answers; no adapter fallback invents an empty response. The transport distinguishes empty accept from cancel, but that direct bridge property is not full Product support. A future explicit canonical empty-text opt-in would need matching persisted-response and UI checks. These repairs change the native closure and require fresh qualification. Profile v7 has paid Product hello passes on local source 807feaecf and Daytona source bd4cc29c3; the latter passed all six matchers with complete owned cleanup. The qualification checkpoint retains exact profile, runtime, image and billing identities. Remaining Product journeys, native interactions and platform coverage are still unqualified; the bd4cc29c3 local campaign passed hello and stopped at native questions: all 15 behavioral checks passed, but the required API evidence snapshot was absent. The failed result is retained and the six later cells did not launch. A committed harness-only fix captures the complete final API evidence; its paid retry passed all 15 native-question checks. The following question-continuation case reached Done but failed the exact final-message assertion: earlier pre-tool narration was aggregated into the final item. Three runs settled across these two cells, all owned processes exited, and five later cells did not launch. The native message attribution defect is repaired in v8; authenticated v8 qualification remains pending. The canonical v7 declaration binds the exact wrapper, helper, extension and three target closures.

Credential-free regressions run the pinned SDK with synthetic model streams to verify all four question methods and original MCP call names behind aliases. The actual patched wrapper proves visible unsupported-dialog failure; the real form normalizer verifies the 1,000-unit ASCII, CJK and surrogate-pair boundaries. The closed snapshot admission test exercises the candidate assets without inference.

Profile version 6 added the native question tool, the authenticated agent-files root, and matching SDK path normalization. Its authenticated Product and Runner qualification is pending. The later v6 Product hello on source 97217c531 passed with one observed attempt and an exclusive-key cost delta of $0.00065884. Its launcher omitted the explicit zero-retry CLI flag, so it is retained as passed_with_retry_policy_gap, never as v7 qualification. The first frozen v6 Product hello attempt fails before provider startup because the shared native-execution parser still admits only profile versions 1–5. Both assignment and automatic recovery runs reject the same input; no usage receipt exists. The early exclusive-key billing delta is $0 and cleanup passes. The retained failure includes the actual local sidecar, Node, daemon, closure and pack identities. The parser repair is included in frozen source edf14a067. Its second hello attempt passes that boundary but fails at the 30-second session.open deadline. No terminal usage exists; both immediate and delayed exclusive-key deltas are $0, and all 40 owned process identities are gone. The v6 startup proof retains that failure and the credential-free diagnosis. Bounded 32-worker file hashing and snapshot copying preserve all integrity checks, canonical ordering, the 32 MiB snapshot batch ceiling, and fully drained failure cleanup. A diagnostic build completes the full no-key Runner rejection in 9.8 seconds; its repeatable protocol regression settles in 10.7 seconds and closes cleanly. A separate actual ACP test asserts the precise missing-credential error. Timings vary with filesystem cache and load; these are admission diagnostics, not authenticated qualification. No timeout or provider-closure identity changes in this repair.

The opt-in regression is node --test test/pi-closed-startup.test.mjs from the Runner package, with PAPERCLIP_TEST_PI_STARTUP_PACKAGE_ROOT pointing at a built Runner package containing Pi assets and PAPERCLIP_TEST_PI_STARTUP_RUNNER_BINARY pointing at its compatible daemon. It spawns a clean environment, submits no prompt, asserts terminal admission rejection within the unchanged 30-second deadline, and verifies the daemon closes. It does not inherit provider credentials.

Historical profile version 5 repairs the Undici dependency and bundled Node runtime affected by GHSA-3wwx-pv8p-q78v. Full authenticated v5 qualification is pending; its bounded native controls probe passes. Historical version 4 repairs native tool ID reuse across model iterations and warm prompts; its native steering, queued follow-up and denied-write probe passes. Historical version 3 passes cover local Product file delivery, typed question continuation and native steering, queued follow-up and denied-write controls. Its semantic plan journey exposed two defects: the shared MCP display projection, now repaired, followed by a resumed-turn ID collision, addressed by v4. Version 2 hello completion and every failure remain retained. The wider local and Linux x64 Daytona matrix remains pending; this document does not promote the candidate to a qualified production runtime.

At this historical pre-1.0 checkpoint, the runner pinned pi-acp@0.0.33 and @earendil-works/pi-coding-agent@0.84.2. The candidate model was openrouter/deepseek/deepseek-v4-flash-0731; only an explicitly bound OpenRouter credential may reach this profile. patches/pi-acp@0.0.33.patch repairs the ACP wrapper. pi-runtime-extension.ts supplies the runner-owned semantic bridge and pre-execution native tool policy. This keeps the upstream session, model, streaming, diff, retry, and compaction implementation while making its missing boundaries explicit.

Capabilities and differences from Codex app-server

Surface Pi implementation and boundary
Sessions Native Pi JSONL create/load; resume is confined to the execution's private session home and original workspace. Cold prompt cannot implicitly load an arbitrary session.
Text and reasoning Native start/end provenance and occurrence IDs separate pre-tool narration from the last completed assistant message; empty or tool-use terminal messages cannot promote stale text. Loaded history is display-only. The common runner's private reasoning policy still applies.
Native tools read, grep, find, ls, write, edit, and bash pass the immutable extension gate before execution. File roots and read-only mode are checked before and after a permission wait. The host sandbox remains authoritative for shell commands and races.
Permissions Native tool approval uses ACP session/request_permission, with allow once, allow for the session, and deny. Only offered options are accepted. Session grants cover an identical operation and still revalidate paths. Questions never become approvals.
Questions The owned paperclip_native_question tool exposes Pi select, confirm, input, and editor through ACP form elicitation. Select is single-choice with stable option IDs. Pi returns false for both No and dismissal of confirm, so the tool reports negative_or_cancelled; it never invents a confirmed answer. Other methods return explicit cancellation. Permissions and semantic Plan approval remain separate.
Agent files Only the authenticated execution's registered agent_files working copy can become AGENT_HOME. The Pi wrapper takes PAPERCLIP_PI_AGENT_HOME from the runner's bound launch, ignores ambient AGENT_HOME, and admits that canonical directory alongside the task workspace. Protected overlap, directory replacement and symlink escape fail closed. Read-only policy still forbids writes. PI_CODING_AGENT_DIR remains private provider state.
Semantic tools Runner-bound HTTP MCP catalogs (numeric loopback HTTP or assigned HTTPS gateways) register under exact mcp__<server>__<tool> names. Calls use an occurrence-scoped delivery ID and preserve the bounded native ID as private ACP-wire provenance, together with the cancellation signal. Common normalized events currently drop that metadata. Authenticated PRP tool handling owns semantic authorization and durable interactions. Only the exact session-assigned gateway URL and credential are used, with redirects disabled. Ambient and unassigned MCP servers are not admitted.
Plans and artifacts Pi has no native structured plan or artifact channel. Paperclip plan and artifact semantic tools remain available through the MCP bridge; native file edits retain bounded, workspace-confined ACP diff projection. Tool text/image results are preserved, and resource blocks are recorded without following URLs.
Steering Capability-negotiated pi/steer issues native RPC steer during an active turn. pi/follow_up explicitly queues native RPC follow_up. Neither is inferred from a second ACP prompt. Each takes {sessionId, message} and returns {accepted: true, sessionId, kind} with the matching control kind.
Usage Prompt results sum actual assistant message usage receipts across continuations. Input, output, cache reads/writes, total tokens and Pi-reported pricing estimates have provenance. Context-window occupancy is not billed usage. No receipt means no usage assertion; absent cache or cost fields remain unknown. Pi calculates cost from its model catalog rates, so this is not an authoritative provider bill.
Retry and compaction The pinned session notice extension preserves bounded, redacted summaries, severity and known native counters/flags separately from assistant text. agent_settled, rather than a transient agent_end, settles a prompt. A final provider error remains a failed prompt.
Images The upstream ACP wrapper accepts image blocks, but AcpxRuntimeTurnInput and the common adapter currently forward text only. P1: implement typed image content through the common converter and then qualify the exact model; live testing alone cannot close this implementation gap.
Cancellation and death Cancellation expires live UI waits and calls native abort. Pi process exit rejects pending RPC requests and all active/queued turns. Partial RPC frames, oversized frames, and malformed JSON fail closed.
Fork and clone Native Pi RPC exposes fork(entryId), clone, and get_fork_messages; the ACP wrapper and Paperclip controls do not map them. P2: add explicit admitted session operations and verified lineage before exposing controls.
HTML export Native export_html is available but unused by this integration. P2: add a bounded workspace artifact export with publication policy before exposing it.
Durable goal and native plan No mapped native surface. Paperclip semantic tools remain the plan path; no Codex parity is claimed.

initialize advertises _meta.paperclipPi.version = 1, steering, queuedFollowUp, the four question methods, nativePermissions, promptUsage, nativePlan: false, and pendingRequestRecovery: "live-process-only". The common host must inspect this advertisement before sending provider extension requests.

Native model instruction delivery (profile version 6)

The fresh/load model-request proof uses the actual pinned wrapper launch helper, owned extension, and Pi SDK AgentSession.prompt with a synthetic model stream. Captured model requests contain the exact composed Paperclip execution prompt, custom instruction-entry content, and current AGENT_HOME guidance. A disk-loaded session retains its prior reply while receiving changed entry content and a new agent-files root in its current system prompt and latest task constraints. The old root is absent from the current system prompt; historical user messages still retain prior root text, which the current guidance explicitly supersedes.

Pi uses PAPERCLIP_PI_SYSTEM_INSTRUCTIONS in its runner-owned launch configuration and appends it through before_agent_start. Generic ACP _meta.systemPrompt is ignored, so that metadata alone is insufficient. This proof captures the native model-request boundary, beyond host options or wire metadata. It uses no real credentials or network inference and does not exercise a complete ACPX/PRP process or qualify an authenticated Product journey.

Occurrence identity (profile version 4)

Pi can reuse a native ID such as call_0 in a later model iteration, including within one ACP prompt. The wrapper and immutable extension now derive one live ID from a private per-child launch namespace, a monotonic model-iteration ordinal, and the native ID. The native turn_start event advances the ordinal; the SDK's relative turnIndex is not authority because it resets on each warm prompt. Permission requests, streamed tools, lifecycle updates and semantic MCP requests share that ID. Bounded private ACP-wire provenance retains the original native ID and iteration. Common ACPX/sidecar normalization drops this _meta; these raw IDs and iteration fields are not currently UI-visible. The normalized delivery ID itself survives the common tool and permission paths. P2: add an allowlisted diagnostic provenance projection and UI coverage without granting the raw ID execution authority. Historical message-index/scope metadata has the same private-wire-only disposition.

An exact HTTP retry reuses the delivery ID and shared cached result. Reusing a native ID for a second invocation in the same iteration, changing its arguments, or receiving ambiguous iteration boundaries poisons identity state and fails closed. Shared Runner bridge deduplication and Rust call tombstones are unchanged. This avoids both replaying a mutation and mistaking a new corrected invocation for an old cached error. Historical session replay uses a separate stable pi-history- identity from session/message occurrence, explicitly marked history-display-only; it never grants execution authority.

The maintained test/pi-native-package-contract.test.mjs regression exercises actual pinned Pi Agent/AgentSession dispatch with an in-memory model stream, empty authentication storage and model networking disabled. Across two warm prompts it verifies six native iterations, relative indices [0,1,2,0,1,2], four reused call_0 executions, extension-before-wrapper ordering, and four matching distinct delivery/display IDs. The authenticated loopback test in pi-runtime-extension.test.ts uses the real Runner semantic bridge to prove cached validation errors, concurrent exact retries, changed-payload rejection, and a corrected invocation in the next iteration. Installed-wrapper tests verify lifecycle correlation and stable, disjoint historical replay identities.

The historical v5 command digest is sha256:020d96ccbd3c45c3f62680814776394ed5a56d9572a1a4dccda56a74d16c7803. Versions 1–4 cannot reopen under this identity. Paid and image proofs below remain evidence of their recorded versions, not v7 qualification. The historical v4 digest is sha256:2324d9b47650c12b16f8e2c44dc33637d52f1b22ba8e914623eac4049e7e1991.

Lifetime and recovery

A provider UI request is a live Pi RPC promise. Paperclip's durable interaction can survive a control-plane connection loss while the runner, wrapper, and Pi process remain alive. A response is forwarded once to that exact pending request. If Pi or the wrapper dies, the interaction must expire; neither a new process nor a loaded JSONL session has the original promise. Do not replay an approval into a replacement process. Normal conversation continuation can load the private JSONL session after a separately admitted restart.

The wrapper attaches a per-turn generation to settlement work, fails queued turns on provider death, and bounds RPC request waits. This does not constitute a claim of generic provider-process handoff or exactly-once external side effects.

Version 6 native boundaries

The native file gate now applies Pi 0.84.2's path interpretation before checking roots: @ prefix removal, home expansion, file URLs and Unicode spaces. Native read also tries macOS screenshot spacing, decomposed Unicode and curly-quote filenames. Every possible fallback is checked, including its physical symlink target, both before and after approval. The prior raw-path check could authorize a workspace-relative spelling that the SDK subsequently interpreted outside the workspace. The actual pinned SDK regression verifies the interpreted path and rejects aliases to private state.

The native question tool accepts {method,title} plus the method's own fields: options: [{id,label}] for select, message for confirm, placeholder for input, and prefill for editor. There are at most 128 unique IDs and unique labels; titles, input fields and answers have UTF-8 bounds. Unsupported fields, unoffered answers and the reserved permission-title prefix are rejected. Exact retries of one native occurrence reuse its pending or completed result. This tool cannot approve a native operation or a Paperclip Plan. Durable semantic questions and revision-bound Plan approval continue to use assigned Paperclip tools.

Credential-free tests exercise all four methods through the actual pinned Pi AgentSession tool dispatcher and separately through the installed ACP wrapper's form transport. They do not establish browser persistence, reconnect delivery, provider-death expiry, or live model behavior. Those remain distinct Product qualification requirements for version 7.

Verified launch and packaging contract

The wrapper rejects ambient launch unless PAPERCLIP_ACPX_ISOLATED_CONTEXT=1. It executes an absolute bound Node executable with an absolute bound Pi CLI path, without a shell or PATH lookup. The common command lease must supply:

  • PAPERCLIP_PI_NODE_EXECUTABLE, PAPERCLIP_PI_ENTRYPOINT, and PAPERCLIP_PI_EXTENSION_PATH: files in the immutable private provider snapshot.
  • PI_CODING_AGENT_DIR: isolated persisted session/auth/settings home.
  • PAPERCLIP_PI_READ_ONLY: exactly 0 or 1.
  • PAPERCLIP_PI_READ_ROOTS and PAPERCLIP_PI_PROTECTED_ROOTS: JSON arrays of absolute allowed skill/read roots and protected runtime/config roots. Assigned skills must use a separate immutable lease outside the protected runtime and executable roots; overlapping roots fail admission. Skill roots are always immutable, even when nested inside a writable workspace.
  • PAPERCLIP_PI_SYSTEM_INSTRUCTIONS: admitted instructions, bounded to 32 KiB.

The wrapper synthesizes PAPERCLIP_PI_RUNTIME_CONFIGURATION for its child, including only session-bound MCP servers. The owned extension captures and deletes this configuration environment variable before model shell execution. Credentials remain accessible only through the deliberately admitted runtime mechanisms.

Pi starts with --no-extensions --no-skills --no-prompt-templates --no-themes --no-approve --offline, followed by the explicit immutable extension and admitted skill paths. Project trust is denied; user-bash RPC and terminal login are disabled. Only the controlled /compact, /session, and /autocompact slash commands are accepted. Startup package update checks are disabled.

The wrapper must not infer complete extension registration from process startup. It therefore probes get_commands and requires the exact readiness sentinel paperclip-runtime-ready-v1 / Paperclip runtime gate v1. The extension registers this command only after gates and every MCP catalog finish initialization. A missing sentinel kills the subprocess before the first model prompt.

pi-verified-runtime.ts inventories and checks the complete graph, including Node, wrapper helper, extension, package metadata, native libraries, WASM and resources. The manifest schema is paperclip.pi-runtime-files.v1, with relative node, piEntrypoint, extension, wrapperEntrypoint fields and a complete files array of SHA-256-bound regular files or contained relative symlinks. Hardlinked files, escaping links, changed files, and undeclared files fail admission. Its verifier returns the three launch environment bindings and a manifest digest. Admission verification alone is not a command lease: the shared host must retain its immutable snapshot and process guardian through termination.

The published Pi package has a shrinkwrap and a nested dependency graph. Provider pack creation must copy the complete installed graph and use the same pinned Pi family dependencies, rather than reconstructing the graph from cli.js imports. The emitted owned extension must be included in every macOS arm64/x64 and Linux x64 pack; the candidate materializer emits it at runtime/extensions/paperclip.js. The wrapper's dist/paperclip-runtime.js is part of its verified package and must never be omitted from a copy or hash.

Verification and maintenance

The v5 offline pack proof binds runtime source aec26ad83f1d082f0d0a5eaffbd615a9e2e26155, combined macOS pack sha256:cf7d0998bbc2bed7b893c726c2b6455ba8a683d9cff7d92afedbff2d5900d500, and immutable daemon sha256:fe03a5f5e7b7d51aafb398aa435e4a200ca6e0206c46b84ba0baa15aa0be5f31. Recursive workspace typecheck and full build pass. Focused checks pass 43 TypeScript tests including actual installation launch, 19 installed-wrapper/native SDK tests, eight materializer tests and 13 Rust backend tests. Independent review recomputed the v5 digest and verified all 13,827 installed files. The security closure proof retains npm's vulnerable pre-replacement result, the fixed installed version, unchanged upstream metadata, target pins and exact runtime file changes.

Both Pi's private interpreter and the separately manifest-bound outer macOS pack interpreter are official Node 24.21.0 with bundled Undici 7.29.1. Sibling provider closure/profile declarations are unchanged. The actual Pi registry initializes ACP1 under a network-denying sandbox, exits EOF0 and releases its process group. Full Runner startup with no credential rejects in 8.558 seconds, below the unchanged 30-second deadline; this is a typed admission failure, not authenticated success. Linux packaging uses the later Docker-only source 94ef513f8; its runtime source trees remain identical to aec26ad83. Linux execution is recorded separately. The two clean lock resolutions match 9eea6018…; tracked lock bytes remain unchanged.

The v4 offline proof binds frozen source f556110d588a9de9fefe676a9a62bf09e98afb85, combined pack sha256:4df7e9fa164929c7ae7d8e8711f0bf7d587d9fa6a246d0a8340f318f57168855, and release Runner SHA-256 373848d2d7287b2c47b2cee422cb7bd25073a594a620a9ad574f2d3d51cd1670. Recursive workspace typecheck and full build pass at that source. Full pack and all three closure inventories verify; the actual Pi registry launch initializes under a network-denying sandbox and exits cleanly on EOF. A separate full Runner startup rejects missing credentials in 11.083 seconds without a prompt. That is a timely admission rejection, not an authenticated success. The proof includes execution-tree identities and two matching clean dependency resolutions.

The v4 focused verification passes 49 TypeScript tests plus the separately enabled actual-distribution installation test (all five installation cases), 24 installed wrapper/native-SDK/materializer cases, and 13 Rust native-provider backend tests. The new macOS arm64 closure was independently reproduced by a fresh locked public-registry installation. The helper tests cover poisoned malformed inputs, iteration overflow and the 4,096-entry limit; installed tests cover cancellation followed by warm native-ID reuse. These checks make no provider inference calls.

The four colocated Vitest suites exercise questions, permissions, timeouts, framing, usage, file policies, MCP behavior, and graph verification. The Node test test/pi-acp-package-contract.test.mjs launches the actual patched npm wrapper against a deterministic RPC fixture. It proves initialization, streaming, terminal usage, question versus permission routing, explicit steering, provider exit, required sentinel, and typed failure settlement. It requires the exact installed pinned package; an absent or unpatched dependency is a failure. PAPERCLIP_TEST_PI_ACP_PACKAGE can select a separately installed pinned fixture. These fixtures invoke no model or paid API.

At source f58cfa1cbf4503b93a0be4480f51b492d8203b7c, all 30 tests in those four Vitest files passed, including the optional actual-distribution installation test. The patched-wrapper, real-Pi, and distribution-builder Node suites passed all 17 tests using the fresh provider-pack packages. TypeScript and the full candidate pack build passed. Retry cases cover successful, failed, and missing outcomes; the failed and missing cases were observed failing against the prior wrapper before the repair. These focused checks do not establish a full repository check or current-head CI pass.

test/pi-native-package-contract.test.mjs runs the real Pi 0.84.2 CLI without credentials. It loads the compiled owned extension, initializes a loopback MCP catalog, and returns the exact readiness command. An invalid catalog exits Pi before RPC admission. This checks the extension ABI and explicit loading path. It does not prove authenticated inference, native tool execution, MCP model invocation, credential renewal, or remote sandbox behavior. Those remain required local and Daytona qualification evidence under the shared live-spend cap. No live inference spend was incurred by these deterministic tests.

The helper in patches/pi-acp@0.0.33.patch is generated from src/drivers/acpx/pi-acp-runtime.ts with Node stripTypeScriptTypes, trimming trailing whitespace. The package contract checks that these bytes match. When updating the upstream version, rebase the wrapper patch and rerun the actual package tests; do not preserve an old qualified command hash after changing bytes.

Primary references reviewed:

Candidate distribution build

Run node packages/paperclip-runner/scripts/materialize-pi-distribution.mjs /absolute/new-output on the target build host. Supported targets are macOS arm64, macOS x64 and Linux x64; no cross-platform qualification is inferred. The builder uses exact official Node 24.21.0, pinned archive SHA-256 and executable SHA-256 for each target. --node=/absolute/portable-node reuses a matching binary; without it the builder downloads the pinned official archive. It rejects non-system dynamic-library dependencies and executes the copied interpreter after relocation. The initial Homebrew Node discovery failed this portability check and is not an admitted pack interpreter.

The isolated scripts/pi-distribution/package-lock.json pins all 143 dependency packages and registry integrity, without changing the workspace pnpm graph. It preserves Pi's upstream nested shrinkwrap, and adds npm registry SHA-512 integrity for the six exact 0.84.2 Pi family packages whose published shrinkwrap omitted it. Installation uses npm ci --ignore-scripts, public registry access, private npm configuration and an environment without npm or provider credentials. The builder checks every locked installed version and upstream shrinkwrap entry (with the exact security exception below), applies the owned ACP patch, verifies the helper matches its TypeScript source, and compiles the owned extension to runtime/extensions/paperclip.js.

Profile v5 replaces only the nested undici@8.9.0 with 8.10.2. Both an existing-lock resolution and a fresh resolution ignore npm's scoped override inside Pi's published shrinkwrap; npm ci also installs 8.9.0 despite the fixed outer lock. The materializer therefore checks the exact original nested path, version, registry URL and SHA-512, plus the installed vulnerable package identity, before fetching the exact fixed tarball. It verifies the pinned SHA-512 before extraction, bounds both gzip and inflated tar bytes to 4 MiB, rejects traversal, links and unexpected entry types, and requires the 214 regular-file payload. The published Pi package metadata and shrinkwrap remain unchanged; only this exact old-to-new tuple is an exception. Every other package retains its previous lock entry. Installed version checks and the complete source-pinned closure then make it impossible for npm's old copy to survive admission.

Node 24.21.0 also replaces bundled Undici 7.29.0 with 7.29.1, covering the global WebSocket implementation as well as the nested npm copy. The materializer checks process.versions.undici explicitly. Sources: official advisory, fixed Undici release, Node 24.21.0 release and official archive checksums. Only Pi's declarations and three closure pins change; sibling provider pins remain unchanged. The containing provider pack must be rebuilt with the patched portable interpreter and retains its own manifest identity.

The result contains runtime/ and a sibling pi-distribution.json. Keeping the manifest outside its inventoried root avoids a self-referential file digest. The returned environment bindings point into runtime/; callers must retain a verified immutable lease on that entire root. Additional native libraries, package files, WASM, data, and templates are all included in the inventory. Only npm-generated .bin symlinks and its hidden installation lock are omitted; launch always uses verified explicit files. The regular-file native-closure.json is independently bound to a trusted per-target source constant. Its pi-entry.cjs bootstrap derives snapshot-relative Node, Pi, extension and module-guard bindings; the Pi subprocess loads the same verified module guard.

The common provider-pack integration uses an explicit --candidate-providers=pi flag. It invokes exported materializePiDistribution into provider-assets/pi/<platform-arch>, records the returned manifest digest and metadata path in the outer pack payload, and includes the entire distribution in the outer pack's integrity proof. The flag prepares an inspectable candidate; it must not change its qualification status or enable admission without required live proof. The default provider pack remains independent of this isolated graph.

On 2026-09-28 the builder completed a real public-registry installation on macOS arm64 with official Node 24.19.0. The resulting complete distribution passed all twelve patched wrapper and real Pi admission tests; those tests never submit a model prompt to a provider. Five builder tests cover the full dependency lock, missing/changed packages, missing shrinkwrap entries, resource mutation, escaping links and unsafe output paths. Linux x64/Daytona and macOS x64 execution remain pending.

Official Node archive and executable pins are recorded in pi-node-pins.ts; archive hashes were checked against the official Node release checksums. The x64 closure pins combine the identical locked package/resource graph with each verified official x64 interpreter. They are candidate artifact identity, not proof that those targets have executed successfully.

Installation authority and token semantics

verifyPiInstallation(profile) admits only the current declared profile version and the source-owned Pi identity. It resolves provider-assets/pi/<platform>-<arch> inside the verified Runner package, checks the complete runtime against source-pinned closure hashes, and opens a guarded immutable native snapshot. The snapshot bootstrap binds Node, Pi, and the extension relative to itself, overriding inherited launch paths. Unconfigured installations return an explicit bound-credential error and expose no terminal login option. The materializer returns the runtime version, profileDigest, and complete closureDigest for the provider-pack manifest.

For the exact OpenRouter qualification model, Pi AI 0.84.2's dist/providers/data/openrouter.json selects openai-completions. Its dist/api/openai-completions.js assigns usage.output from completion_tokens, which already includes reasoning tokens; usage.reasoning is a subset. PRP must therefore use zero additional thought tokens for this pinned profile, rather than counting that subset twice. Missing cache categories remain unknown at the wrapper receipt boundary. usage.cost is a Pi catalog pricing estimate, never an invoice.

The closed snapshot has been exercised against actual pinned Pi through ACP initialization and the missing-credential admission path without a model call. The first authenticated local Runner snapshot verified the exact configured model ID. It did not settle or produce a terminal usage receipt; complete local and Linux/Daytona receipt qualification remains outstanding.

Historical profile version 3 declaration digest: sha256:72cb225288376f733b9ed3afa5e13565eb4152f0de509bc1181382fa44bee472. Each profile digest hashes its versioned profile domain, patched wrapper source and platform closure pins. Every native closure remains independently checked at launch. Version 1 through 5 warm sessions cannot be reused with this integration.

Pi 0.84.2 emits compaction_start/compaction_end; the wrapper maps those events, includes terminal result.usage receipts once, and retains bounded summarization retry progress. Manual compaction requires an idle session and has a 120-second RPC deadline; deadline expiry terminates Pi so a timed-out operation cannot continue invisibly. Successful compaction reports assistant_message_and_compaction_receipts provenance. Pi's summarization retry helper discards failed-attempt usage, so any retry or missing compaction receipt invalidates complete-turn token/cost totals instead of inventing complete coverage.

The retained macOS ARM64 provider-pack admission proof records source 7710736ca3924c655c5b0efd172cfd3c0173766a, with version 3 runtime source 06cf356a8bc94f709fcd15606fe05e17933fe3b2. The latter differs only by the capability report and Pi evidence JSON; all execution tree hashes match. Its manifest digest is sha256:eb31cadae93805b901d2565912121fca6e79024c0120b1bd7982e05215b5aa5a. Two independent clean dependency resolutions match 2c46a68811ba1d504a41b6f4d3f642bc93f4a1c615097754c9c6486881dba8e6. The generic installation registry and immutable snapshot passed initialization and rejected the exact missing-bound-credential error before any model prompt. Full Runner session.open terminated with typed rejection in 12.111 seconds, below the unchanged 30-second deadline; this is not authenticated success.

Version 3 verification passes TypeScript and release Runner builds, 95 focused Vitest cases in seven files including actual-distribution launch, 25 installed package/receipt/materializer checks, and 16 native-provider Rust tests. These checks do not constitute full repository verification or paid qualification. The version 2 dd78 proof retains the earlier pack used for hello, model admission and restrictive denial. Its 107 Vitest checks and 22 installed checks remain tied to that source.

The 9f2d0420e proof retains the earlier source and pack that reproduced the startup timeout. Its 97 Vitest checks and 22 package checks, including the corrected explicit package-path invocation, remain historical evidence.

The a6167ce3a proof and 58511d79d proof remain historical observations. The 128 targeted checks, 31 installation checks and 17 package checks remain pinned to 58511d79d; the full Runner suite (2,202 passed, 11 skipped) and 13 native-provider Rust tests remain pinned to 2e65b64d5. They are not relabeled as checks of the latest source.

The pre-launch-boundary proof retains source 2e65b64d5a2148583109b8157d6e72f54f5ad29b and manifest sha256:7300b9c449c02b61d2f93ef765f371c277e39a58d04739c6c24dcf7939500701, including the full runner suite and native-provider Rust results. It predates the final runner environment allowlist and direct candidate-admission fixes.

The pre-policy proof retains source d039e1b7b072862b4c326ba7194dc42617fa5984 and manifest sha256:5a47fc67b886c1e05d0f630ed89c1b9f5324610b649d1db020a3e036e36fc85d, including its cleanup-timeout retry history. It predates the Node engine metadata and corresponding manifest/closure identities.

The previous integrated proof retains source f58cfa1cbf4503b93a0be4480f51b492d8203b7c and manifest sha256:3de76fb7d3902d29285e3da51e36d2ba4654c29bab0c867a6209fadea77c2181. It covers the retry-status repair before the HTTPS and shared runtime fixes. The earlier integrated proof retains source 1e0d11c482f8ef50b6afc1430cb736579114b266 and manifest sha256:f859e30e51326ff875d616e2bb3fd4c0246ce1f58a5988968b91bae176a68281 with its narrower capability assertions. These files are historical evidence, not proof of the current executable bytes. Later runtime or foundation changes require a new pack build and source-pinned admission record.

Remaining event and qualification work

The candidate preserves the core request/response paths. It does not preserve every field in Pi's native event stream. These are explicit follow-ups:

  • P1 — retry/compaction field completeness and end-to-end evidence. At source 41503eb38f03c436b1569f9f0204625bb4d58782, the wrapper emits bounded paperclip/pi_notice activity instead of assistant text. The adapter preserves source provenance, attempt, maxAttempts, delayMs, success, aborted, willRetry, enabled, and bounded reason/errorMessage fields when supplied. The UI renders the notice details. finalError is not forwarded, and summarization retry currently has summary-only data. Package regressions cover retry success/failure/unknown and compaction usage; adapter tests cover bounded metadata and redaction. Extend field-by-field wrapper/canonical/browser parity without giving notices terminal authority or treating deterministic tests as paid qualification. See the wrapper patch, notice adapter, package regressions, adapter regressions, and UI details.
  • P1 — native queue state. queue_update contains steering and follow-up queues. Extension calls acknowledge RPC acceptance, but the wrapper does not project that event into durable queued/delivered state. Do not treat {accepted: true} as proof that a later model turn consumed a message. Queue contents are also user content, so any added projection needs explicit retention rules. Next: emit bounded, occurrence-bound queued/delivered notices and distinguish acceptance from actual consumption; preserve queue content only under the existing content policy.
  • P2 — extension UI and configuration. setStatus, setWidget, setTitle, and set_editor_text messages have no Paperclip UI projection. The admitted extension does not use them. notify retains a bounded message and severity, while interactive select, confirm, input, and editor have the explicit response bridge. Native session-name and thinking-level change events also lack a separate event projection. The wrapper advertises ACP thinking-level configuration, but the current Runner host does not expose set_mode or set_config_option; no reasoning-level override was applied during qualification. Next: define bounded status/widget/title dispositions and explicit typed configuration controls; require a provider acknowledgement before claiming a setting changed.
  • P2 — files and artifacts; P1 — image input. File diffs are bounded text snapshots, not complete binary changes or durable artifact publication. Semantic artifact tools remain the supported publication path. Image prompting, model-triggered tools, approvals, typed questions, explicit steering, warm recovery, and live usage need authenticated local and Linux x64 Daytona proof for the exact declared model. The reported model ID must be checked, rather than inferred from the configuration. Next: implement image content through the shared text-only converter, qualify actual model content handling, and separately test diff/artifact publication boundaries.

Authenticated local qualification progress

The v5 native controls proof passes the unchanged probe on frozen aec26ad83 / pack cf7d0998… in 19.199 seconds. The original write invocation pi-849b369266c920633abffa988509e4ba61fcdf464f62c73900fd5ddd6d477402 correlates with the denied failed-tool update. The decision is fsynced before either control request; both control acknowledgements precede sending the original denial response. Visible output is exactly STEERED_CURRENTQUEUED_NEXT, stale steering rejects, the forbidden file remains absent, and the turn settles end_turn. Child, verified lease and temporary workspace cleanup complete; an independent process check finds no remaining probe or Pi process. No database is started. Actual usage is 3,727 input, 140 output and 1,792 cached-read tokens. Delayed exclusive-key billing settles at $0.000151739; the separate Pi catalog estimate is $0.000611156. Initial unchanged reads are retained, not interpreted as free inference. This proves direct native controls and denial on the patched profile; it does not qualify Product recovery or remote execution.

The v4 native controls proof passes on frozen f556110d5 / pack 4df7e9fa…: one native write request uses the same normalized invocation ID in its persisted decision and failed tool update; the original deny option is written only after both control acknowledgements. Visible output is exactly STEERED_CURRENTQUEUED_NEXT, stale steering is rejected, the forbidden file remains absent, and the prompt settles end_turn. Cleanup completes without a database. The terminal receipt contains 2,030 input, 1,293 output and 5,632 cached-read tokens. A later billing observation settles this attempt at $0.000546502; Pi's separate catalog estimate is $0.000803936. Initial unchanged billing reads are retained and were not treated as free inference.

A newly indexed Undici advisory affects the historical v4 isolated npm Undici 8.9.0 and Node 24.19.0's bundled Undici 7.29.0. Profile v5 fixes both copies as described above. The separately authorized v5 control proof uses that repaired closure; no further paid case is authorized. This paid v4 proof remains bound to its original bytes.

The first v4 plan attempt failed before provider startup: embedded PostgreSQL could not initialize the Product fixture. Canonical classification is transient_infrastructure, with zero provider prompts and two unchanged post-attempt key-billing observations. The fixture directory is gone and no matching process remains. A later read-only host snapshot shows 87,263 of 87,381 SysV semaphores in use, supporting a resource constraint. A separate disposable diagnostic then reproduces the cause with the same pinned PostgreSQL binary: semget(..., 17, 03600) fails with No space left on device when only 16 semaphores are free. It exits in 0.557 seconds, removes its temporary directory, leaves no child process, and leaves IPC totals unchanged. The original Product bootstrap stderr remains unavailable. No unrelated database or IPC object was changed during that diagnosis. The later user-approved fixed-snapshot host cleanup removed 4,892 stale semaphore sets and skipped 11 whose recorded creator PID was present. Startup and graceful shutdown now pass; the current checkpoint above supersedes this historical qualification hold.

The sanitized attempt ledger retains all twenty attempts, including eight failures before a model prompt. One Runner protocol turn reached the exact model and successfully called get_task_context, get_task_history, list_documents, and read_document. The canonical case permits those extra orientation reads, but also requires a completed turn; it timed out after 120s without terminal usage. The later Product hello journey passes; the canonical Runner protocol case has not yet passed.

Exclusive OpenRouter key billing increased by $0.028858372, including $0.000351509 from the sleep-interrupted Product attempt and $0.000654767 from the successful hello journey, plus $0.010995043 across the restrictive-denial and file-edit batch. A delayed charge crossed the latter attempt baselines, so that batch is accounted as an aggregate without per-generation attribution. Version 3 file, question and failed plan cases add $0.007828938. The version 3 native controls probe adds $0.000140985 after a later key reading resolves its initially unchanged observations; those early reads did not prove free inference. The seven pre-prompt failures had two post-attempt observations with zero delta. This is measured provider spend, separate from Pi's stale catalog pricing estimate. A missing terminal receipt remains unknown, not free execution. Each attempt had no automatic retries, a $2 reservation and a $0.50 billing watchdog; the Product supervisor also imposed a 300s outer deadline.

The paid trace exposed a shared projection defect: canonical item.delta events with kind: reasoning were relabeled as assistant messages by the TypeScript facade. Shared commit a978d1bc5 preserves summary/detail reasoning channels, including mixed coalesced batches, so the existing private-reasoning redactor applies. Three regressions failed before the fix; 20 focused checks, 8 additional Codex event checks and source typecheck passed afterward. Hidden reasoning is excluded from this report and the published ledger. The provider timeout remains a separate unresolved result.

Product hello first failed before startup because the local PostgreSQL package's symlink hydration had not run. Its bundled setup script repaired the installation and a fresh database initialization passed. The deliberate repeat reached the real browser/server, then candidate agent creation returned 422 because the provider-profile validator still rejected candidates before the host's explicit qualification admission boundary. Shared commit 26dde3cfe corrected that gate. The next attempt created the agent and task, then found a dormant Pi-only rejection in the verified runnerd backend factory (transportDriverIdentity); it again submitted no model prompt and incurred zero measured billing delta. The shared identity correction is included in foundation c3b7e9ecd. The next attempt passed those guards but stopped at PRP command session.open timed out after 36.5 seconds of run startup; cleanup passed and the measured key billing delta remained zero. It produced no terminal usage receipt or matcher success.

The canonical live-eval completion contract had a separate defect: fresh sessions omitted native paperclip_finish/paperclip_block schemas, their callback rejected otherwise valid native reports, and ACP model instructions lacked the literal contract revision. Shared commits dc58afb28 and aa4b88b16 expose and validate those advisory reports and send the exact contract on fresh/resumed sessions. They cannot mutate mock tasks, grant semantic permissions or settle the provider turn early. Two declaration/acceptance regressions and one instruction-delivery regression failed before repair; 45 live-session tests and three focused follow-up checks passed, with source typecheck. This is a confirmed protocol defect, but its causal contribution to the earlier model timeout is not proven.

The startup diagnostic reproduces that failure without credentials through the deployed Runner transport. Its run.prepare command completes, while session.open remains pending at the unchanged 30-second deadline. Separately timing the same 13,827-file, 234 MB closure measured 5.168 seconds of verification and 37.423 seconds to construct its immutable snapshot, before any Pi process starts. Shared fix 2a30219f1 copies at most eight files and 32 MiB per batch, with larger admitted files alone. It retains every file identity, digest and confinement check and drains all copy promises before cleanup. The same tree then copied in 5.851 seconds; ten security and concurrency tests and both Runner TypeScript checks passed. The rebuilt dd78df1e pack then settled the full credential-free Runner session.open request in 10.087 seconds (10.198 including close), within the unchanged deadline. It returned terminal session_ensure_failed; the outer PRP response omits the underlying credential error. The independent immutable ACP probe from the same pack asserted the missing-credential error directly. This is timely rejection, not authenticated session success. The earlier timeout attempt retains its original source identity.

The next Product attempt (hello05, source dd78df1e) reached an authenticated session in 11.631 seconds, submitted a turn and received turn.accepted. It then crossed a confirmed macOS Maintenance Sleep of 888 seconds. The retained browser trace ends without a semantic-tool or terminal event; completion and usage are unknown. The canonical result remains failed/secret_leak: the evidence scanner could not inspect an incomplete ZIP (unzip exit 9), rather than detecting a credential-value match. Browser cleanup also failed after wake; a later process check found no remaining process from this exact attempt. Both the canonical 921.632-second wall duration and supervisor 72.168-second monotonic duration are retained. This result proves startup admission, not a completed Product journey. The explicit retry adds an idle-sleep assertion and a wall-clock supervisor bound without changing the provider timeout, canonical oracle or evidence scanner.

The explicit hello06 Product proof passes all six canonical matchers, including the exact response once, task done, run succeeded, native runtime and local environment. Pi executes mcp__paperclip__paperclip_finish, then reports a completed turn and succeeded run. The case took 32.668 seconds; cleanup and evidence inspection passed. Its receipt contains 26,867 input tokens, 283 output tokens and zero cached input tokens. The catalog notice estimates $0.00384062; measured key billing is $0.000654767. Product correctly marks dollar coverage unpriced and incomplete. These values are not interchangeable.

The separate authenticated model-selection proof sends no prompt and measures zero key billing delta. It reads the actual ACP model response, selects the declared model, and observes openrouter/deepseek/deepseek-v4-flash-0731 after Pi's native RPC state refresh. The Product path enforces this comparison before prompting, but its retained session.started model metadata says unknown; final usage carries the configured identity. The separate proof closes model-selection evidence without pretending it came from that Product transcript.

The historical version 2 pack, model and hello proof JSON files retain Git tree hashes for Runner source, scripts, Rust, protocol, patches, server source and Product E2E. Those version 2 observations stay pinned to dd78df1e when later commits change only these reports and fixtures; an execution-source change requires a fresh build.

Execution source path Git tree at dd78df1e
packages/paperclip-runner/src a8123cb4396c77ce0127d5ccf49d3584b63a9a58
packages/paperclip-runner/scripts 9ede97769bb3f2bbfa8e02be220b5ce06e438a99
packages/paperclip-runner/runner 2cc84e150aecbd5faf2c8bcecc4b6352c24dbca8
packages/paperclip-runner/protocol 1d50458fb572d0c75f9a398f419209c52c23ba6f
patches 1e2f846b8b2dda202b79ee83baeb0860a3b9ab64
server/src b267adc1e0ad36955b68314829cfd4256ab88d37
tests/runner-e2e 5ff4b8a85a14e3e005e3e240c145899c0bc742b5

Production admission remains qualification-pending until the live matrix and spend receipt checks pass.

Version 3: retain failed tool validation and Bash results

The version 2 file-edit Product attempt exposed an owned bridge defect: five paperclip_finish calls returned failed MCP results, but the extension replaced all authenticated validation text with a generic rejection. Version 3 keeps valid text and structured error details within an 8 KiB UTF-8 bound, redacts bound credentials and labelled secrets, and still raises a failed tool result. Malformed or oversized errors remain explicit failures. The original five call arguments were not retained across the privacy boundary, and the fixture's workspace was removed during cleanup, so this report does not reconstruct their contents or assert that the file oracle passed.

A separate Bash projection gap discarded native result fields because upstream sent them only as private terminal metadata. The wrapper now also emits standard ACP rawInput and rawOutput, preserving each structured value whole up to 64 KiB and marking larger values omitted. Installed-process fixtures cover success, failure, partial output and the size boundary. Canonical exitCode remains unknown: the shared projection does not yet map the native structured field, and this patch does not infer it from text or success status.

These changes alter the immutable wrapper and owned extension. All three target closure pins and the versioned profile digest change; version 2 warm snapshots are rejected. Earlier local hello, restrictive-denial and Linux initialization proofs remain tied to their version 2 execution source. Version 3 must complete fresh paid qualification before those behaviors can be claimed for its bytes; the new immutable-pack checks above pass.

The restrictive-denial proof retains the version 2 real native write rejection: the original offered decision was durably recorded before responding, the matching tool failed, the prompt settled, and an independent filesystem check found no forbidden marker. This is direct ACP delivery proof; it does not exercise PRP restart replay.

The file-edit failure retains the candidate timeout, five generic finish errors, missing file oracle, unknown terminal usage and successful process cleanup. These failures are kept alongside the version 3 corrections rather than overwritten by a future retry.

Version 3 live evidence

The file delivery proof passes all seven canonical matchers. The independent oracle reads the exact 24-byte workspace file before cleanup. The first finish request fails because a workspace-only file is not downloadable; the retained validation message tells Pi to register the deliverable. Pi does so and then finishes successfully. The browser shows the download card and Done status. All five Bash results are non-null; canonical exit code remains unknown. The case measured $0.003324737. No separate raw copy of the workspace file was retained.

The typed question proof passes all six matchers. The browser submits option ID cobalt for question ID verification-word; the same durable interaction becomes answered and a distinct warm continuation completes. The pending form and final answer were visually inspected. This is continuation without server restart. The waiting run has no usage receipt, while the continuation has one; total token coverage remains partial. The measured key delta is $0.001413697.

The plan failure retains a complete two-step Plan at revision 1 and an unanswered confirmation bound to that exact revision. The provider run succeeds and the task remains in review. The real browser trace shows task-chat-plan-preview-fallback inside a settled turn. Rust had retained mcp__paperclip__write_document as a builtin tool with no namespace, so the UI could not embed the Plan at its write_document boundary. The meaningful canonical matcher remains unchanged. No approval was submitted, terminal usage is unavailable, and the measured key delta is $0.003090504. Shared repair 5aa02662b restores MCP name/namespace/transport while preserving operation authority. Its negative fixture retains the observed fallback, and the positive settled-turn UI regression passes. A fresh daemon and new source-pinned live run are still required.

The native controls proof submits one ACP prompt to the actual selected model. While its native write waits for permission, both explicit controls acknowledge the same active session. The original offered denial ID is persisted and fsynced before the pipe response. Visible output is exactly STEERED_CURRENT followed by QUEUED_NEXT; a matching failed tool update and independent absent-file check prove the denied write. The prompt settles and a later steering request is rejected as stale. The native receipt reports 1,941 input, 134 output and 3,584 cache-read tokens. Its $0.000409612 catalog estimate differs from the later measured $0.000140985 key delta. This proves consumed controls on a live process, not durable queue replay after process replacement.

All four observations use immutable pack eb31cada… at source 7710736ca…, with runtime source 06cf356a8…; they predate the combined provider integration 7ab463697…. Execution tree hashes are retained in the Product proofs. The Linux x64 proof uses profile version 3 at source 06cf356a8…, image sha256:c5fa7976bba92a186a2f70dc8b8ddc58ab86606b80a819c89bf550d2d057c832. It launches the verified native wrapper, initializes ACP protocol 1 and exits cleanly on EOF with network disabled and no credentials or model prompts. This proves Linux executable admission; authenticated Daytona behavior remains pending.

The explicit plan02 follow-up uses combined pack 0800f101… from source 7ab463697… and fresh daemon 955d0714… from e35b11db2…. It passes the repaired Plan presentation boundary and accepts the exact revision. The resumed run then fails after 120 seconds. Its first finish request receives a precise completion-criterion correction, but the next finish and context read fail with duplicate call identity conflicts. All three distinct operations reuse native ID call_0; the extension forwards that ID unchanged into the shared MCP dedupe boundary. This is a further integration defect. The shared dedupe guard and canonical grader remain intact. Both runs lack terminal usage; measured billing is $0.002440082 and cleanup passes. Restart and refreshed hello are held until this defect is repaired.

Explicit host installation

For a published local Paperclip installation, run paperclipai runtime setup pi with the same installed CLI and account that owns the server package. This is an explicit download and verification step; npm installation and agent launch never perform it automatically. It installs only this host's supported platform (macOS ARM64, macOS x64, or Linux x64), using the source-pinned Node archive, npm lock, wrapper patch and complete Pi closure. Node 24, npm, git, tar and the normal platform dependency inspector (otool or ldd) must be available. The server package must be writable by the installing account. Explicit setup preserves HTTP_PROXY, HTTPS_PROXY, NO_PROXY, their lowercase equivalents, SSL_CERT_FILE, SSL_CERT_DIR and NODE_EXTRA_CA_CERTS for public downloads, and enables Node's environment proxy handling. The provisioner keeps the same closed allowlist. Instance settings, provider credentials, user npm configuration, HOME, NODE_OPTIONS and NODE_PATH are excluded; TLS certificate validation stays enabled.

The public server carries a self-contained setup tool and small pinned inputs in dist/vendor/paperclip-runner/cli; the installed host closure lives in that server package's provider-assets/pi/<platform>. Setup validates an existing closure again before accepting it. A corrupt existing installation is left untouched and rejected; reinstall the same Paperclip release into a clean package location and repeat setup. Concurrent setup is rejected. Cancellation drains the current bounded download/build command before removing its private staging tree; allow that cleanup to complete before trying again.

Then select Pi with an explicit provider/model ID and bind its provider credential through the normal agent environment configuration. Setup itself makes no model request. A missing host closure produces explicit setup guidance. Daytona uses the separately built and verified Linux provider pack in its runner image; running local setup does not install or qualify a remote image. Published-tar local and Daytona startup evidence must bind the final installation candidate, with no candidate qualification flags, before a production-readiness claim.

Cold process admission budget

Pi cold session.open, including process replacement and durable reopen, has a 60-second admission budget. The controller shares one deadline across its cold open/recovery command and provider identity barriers (session.open, replacement run.attach, and replacement runner.drain). A live adopted runner keeps the ordinary 30-second waits. Rust gives only Pi's sidecar session.open request the 60-second budget; initialize, attach, turn start and other sidecar commands stay at 30 seconds. Inner ACP handshake (30 seconds), post-admission verification (8 seconds), cancellation (2 seconds), and close (7 seconds) are unchanged.

Timeout still poisons and retires the Rust sidecar process group. Closing the controller during its startup wait rejects that wait and uses the existing owned process cleanup. Callers must await transport close in their cleanup path. This is trusted controller timing policy, outside the immutable Pi wrapper/profile closure; it does not change profile 13, runtime 1.0.0, or the explicit model.

The credential-free closed-startup regression requires the real session_ensure_failed rejection within 60 seconds, with no prompt, no provider identity and confirmed cleanup. Its child watchdog is 80 seconds (20 seconds for cleanup after admission), inside a 90-second test timeout. Failed evidence stays in its reported temporary directory. These margins do not extend production command deadlines or qualify a target platform without a fresh run.